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