最近我开始使用多线程并且一直在努力更好地理解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()方法的完成?
我假设它与返回任务有关,但我无法弄清楚如何取得进展。
感谢任何帮助。谢谢!
答案 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
用于事件处理程序。