Await / Async和Task的澄清

时间:2015-06-02 15:10:03

标签: c# multithreading asynchronous

最近我开始使用多线程并且一直在努力更好地理解await / async和Task。我输入了以下情况:

private void button1_Click(object sender, EventArgs e)
{
    var list = GenerateList();
    progressBar1.Maximum = list.Count ();

    CreateStuff (list));
    MessageBox.Show ("Complete!");
}

async void CreateStuff (List<int> list)
{
    //additional Parameters here used for DoWork()
    await Task.Run (()=>Parallel.ForEach(list, item =>
    {
        DoWork();
        Invoke(new Action(() => progressBar1.PerformStep()));
    }));
    //do something that relies on list
}

我试图在CreateDocs方法完成后显示消息框。同行告诉我,在CreateStuff()方法中可以继续使用等待异步,并且在我显示消息框之前仍然等到方法强制执行。我一直在研究等待异步和任务一段时间,似乎无法弄清楚如何做到这一点。

对我来说,使button1_Click()使用等待异步,然后等待CreateStuff()方法似乎要容易得多。

我的问题是:是否可以在CreateStuff方法中继续使用await async,并且在显示消息框之前仍然等待button1_Click()中CreateStuff()方法的完成?

我假设它与返回任务有关,但我无法弄清楚如何取得进展。

感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:6)

  

我的问题是:是否可以在CreateStuff方法中继续使用await async,并且在显示消息框之前仍然等待button1_Click()中CreateStuff()方法的完成?

绝对 - 但您需要先更改CreateStuff的返回类型。目前您正在返回void,这几乎不是一个好主意 - 它实际上只适用于事件处理程序。您需要做的就是将其更改为返回Task,您可以等待它:

async Task CreateStuff (List<int> list)

然后在你的点击处理程序中(也需要异步),等待调用它的结果:

await CreateStuff (list);

根本不清楚CreateStuff的实施是否真的很理想,请注意。你不需要异步方法 - 你可以拥有:

Task CreateStuff(List<int> list)
{
    return Task.Run(() => Parallel.ForEach(list, item =>
    {
        DoWork();
        Invoke(new Action(() => progressBar1.PerformStep()));
    }));
}

当你只能返回任务并让调用代码等待它时,有一个异步方法只是创建一个任务并等待它,这一点并不多。 (我怀疑,它们在某些方面的表现略有不同,但在这种特殊情况下并不是很重要的。)

答案 1 :(得分:2)

您的问题是async void

您需要将CreateStuff()更改为async Task,以便您可以在呼叫现场await

您只应将async void用于事件处理程序。