0
我有一个单例类的winforms应用程序,它包含一个属性(列表),它是搜索网格的数据源。填充此属性需要大量的时间(> 1分钟),因此,我想在用户启动程序时异步开始填充此属性。单例异步加载列表属性
主窗体有一个按钮来启动另一个搜索表单。如果用户在数据源准备就绪的情况下启动搜索,则没有问题。但是,如果数据源仍在填充,用户将看到一个等待光标,并在数据源完成填充后立即填充搜索网格。
为此,我创建了一个方法,在异步方法完成后触发,然后将网格绑定到数据源。
一切似乎正常工作,事件触发,然后我尝试将列表绑定到网格,没有任何反应......调试暂停,我从来没有击中下一行代码(请参阅FrmSearch.cs中的注释) 。
任何有关什么是错误或一般代码改进的想法将非常赞同,谢谢!
的Program.cs
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Task.Run(async() => { Singleton.DogsList = await Dogs.FindAllAsync(); });
Application.Run(new FrmMain());
}
}
Singleton.cs
public static class Singleton
{
public static event DogsListHandler DogsListLoaded;
public delegate void DogsListHandler(object sender, EventArgs e);
public static BindingList<Dogs> DogsList
{
get
{
if (dogsList == null)
{
Task.Run(async() =>
{
dogsList = await Dogs.FindAllAsync();
notifyListLoaded();
});
}
return dogsList;
}
set { dogsList = value; }
}
private static BindingList<Dogs> dogsList;
private static void notifyListLoaded()
{
if (DogsListLoaded != null) { DogsListLoaded(null, EventArgs.Empty); }
}
}
FrmSearch.cs
public partial class FrmSearch : Form //launched using the .Show() method from a button on the main form
{
public FrmSearch()
{
InitializeComponent();
}
private void FrmSearch_Load(object sender, EventArgs e)
{
Singleton.DogsListLoaded += new Singleton.DogsListHandler(Dogs_ListLoaded);
Cursor = Cursors.WaitCursor;
if (Singleton.DogsList != null)
{
grid.DataSource = Singleton.DogsList;
Cursor = Cursors.Default;
}
else { Cursor = Cursors.WaitCursor; }
}
public void Dogs_ListLoaded(object sender, EventArgs e)
{
grid.DataSource = Singleton.DogsList; //freezes here
Cursor = Cursors.Default; //this line never gets hit
}
}
Dogs.cs(将拉动从数据库通常只是做一些重复的样品)
public class Dogs
{
public string Name { get; set; }
public string Breed { get; set; }
public int Age { get; set; }
public string Summary { get { return string.Format("Name: {0}/Breed: {1}/Age: {2}", Name, Breed, Age.ToString()); } }
public static async Task<BindingList<Dogs>> FindAllAsync()
{
BindingList<Dogs> dl = new BindingList<Dogs>();
await Task.Run(() =>
{
int i = 0;
while (i <= 999999)
{
dl.Add(new Dogs() { Name = "River" + i.ToString(), Breed = "Border Collie", Age = 3 });
dl.Add(new Dogs() { Name = "Jack" + i.ToString(), Breed = "Labrador", Age = 2 });
dl.Add(new Dogs() { Name = "Emma" + i.ToString(), Breed = "Beagle", Age = 7 });
i++;
}
});
return dl;
}
}
aync属性...似乎是一个坏主意。如果你需要潜入数据库,它应该是一种方法。由于您可以等待“任务”或“任务”,因此您无法等待属性。你需要做一些重新设计!你甚至不使用线程安全集合。 –
嗨,彼得,我添加了上面的dogs.cs类。在我真正的应用程序中,是的,它确实从db中拉出来,但对于dogs.cs示例,我只是在做一些迭代。狗类确实返回一个任务>。我是新来的异步。任何关于重新设计的建议? –
beeker
您应该查看['NotifyTaskCompletion'](https://msdn.microsoft.com/zh-cn/magazine/dn605875.aspx)它是专为处理异步绑定而设计的,就像您正在尝试执行的那样。这是[最新版本的GitHub页面](https://github.com/StephenCleary/AsyncEx/wiki/NotifyTaskCompletion)。 –