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)。 –