Await/Async 和 Task 的说明

Posted

技术标签:

【中文标题】Await/Async 和 Task 的说明【英文标题】:Clarification for Await/Async and Task 【发布时间】:2015-06-02 15:10:02 【问题描述】:

最近我开始使用多线程,并试图更好地理解 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() 方法中继续使用 await async,并在显示消息框之前仍然等待该方法完成。我一直在研究 await async 和 Task 一段时间,但似乎无法弄清楚如何做到这一点。

对我来说,让 button1_Click() 使用 await 异步,然后 await CreateStuff() 方法似乎更容易。

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

我假设它与返回任务有关,但我不太清楚如何进行。

感谢任何帮助。谢谢!

【问题讨论】:

【参考方案1】:

我的问题是:是否可以在 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()));
    ));

当您可以只返回任务并让调用代码等待它时,存在仅用于创建任务并等待它的异步方法并没有多大意义。 (我怀疑它们的行为在某些方面略有不同,但在这种特殊情况下并不重要。)

【讨论】:

通过使用 await CreateStuff(list);在我的点击处理程序中,我还需要将异步添加到点击处理程序吗?而在我修改程序之前,我正在等待 CreateStuff 中的 Task 完成打印一行。 @user3311482:是的,您也需要点击处理程序是异步的,但这很简单。 出于好奇,将点击处理程序设为异步是否被认为是不好的做法? @Speerian: 不 - 事件处理程序基本上是异步方法允许返回void的唯一原因......而且它工作得非常好,因为你可以等待长时间运行的操作,然后访问 UI,因为继续在 UI 线程中触发。【参考方案2】:

你的问题是async void

你需要把CreateStuff()改成async Task,这样你就可以在调用点await了。

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

【讨论】:

以上是关于Await/Async 和 Task 的说明的主要内容,如果未能解决你的问题,请参考以下文章

Unity中的异步编程——在Unity中使用 C#原生的异步(Task,await,async) - System.Threading.Tasks

C#异步编程概念和使用

探究SynchronizationContext在.Net异步编程中的地位

async / await 的串行和并行

promise与async和await的区别

js异步回调Async/Await与Promise区别 新学习使用Async/Await