我在ToolStripDropDownButton
上有一个ToolStrip
和一个返回项目列表的异步方法。为了简单起见,我们假设这个方法如下:
private async Task<List<String>> getItems()
{
await Task.Delay(100);
return new List<String>() { "test 1", "test 2" };
}
我想要达到的目的是:一旦用户点击ToolStripDropDownButton
,我想用下面的异步方法返回的项填充下拉列表。
根据需要填充DropDownItems
集合的显而易见的地方是DropDownOpening
事件处理程序。
我尝试了以下内容:
private async void toolStripDropDownButton1_DropDownOpening(object sender, EventArgs e)
{
toolStripDropDownButton1.DropDownItems.Clear();
var items = await getItems();
foreach (var item in items)
toolStripDropDownButton1.DropDownItems.Add(item);
}
但是没有使用这种方法显示下拉。我想在await
之后,下拉已经消失了。
所以我的问题是:如何使用异步方法返回的项目填充下拉按需,而不会在等待项目时阻止GUI线程?
请注意,在等待项目时阻止GUI线程(例如,如下所示)会导致死锁。
private void toolStripDropDownButton1_DropDownOpening(object sender, EventArgs e)
{
toolStripDropDownButton1.DropDownItems.Clear();
var items = getItems().Result;
foreach (var item in items)
toolStripDropDownButton1.DropDownItems.Add(item);
}
答案 0 :(得分:0)
您可能应该填充项目列表,以便在之前之前显示给用户点击下拉列表。当列表有效时,您必须查看应用程序的最佳时间。
我会说当表单加载或初始化时可能是一些更好的选择。然后使用async
将意味着您的GUI在后台检索项目时仍保持响应。
答案 1 :(得分:0)
我发现使用Click
事件代替DropDownOpening
事件,然后在结束时调用ShowDropDown()
:
private async void toolStripDropDownButton1_Click(object sender, EventArgs e)
{
toolStripDropDownButton1.DropDownItems.Clear();
var items = await getItems();
toolStripDropDownButton1.DropDownItems.Clear();
foreach (var item in items)
toolStripDropDownButton1.DropDownItems.Add(item);
toolStripDropDownButton1.ShowDropDown();
}
这会产生一些闪烁,但我可以忍受。