在DropDownOpening上异步填充DropDownItems

时间:2014-12-17 10:08:30

标签: c# winforms asynchronous drop-down-menu async-await

我在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);
}

2 个答案:

答案 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();
}

这会产生一些闪烁,但我可以忍受。