我从异步中了解原理实际上存在一些问题。有人能告诉我下面的代码示例之间的区别吗?如果有人认为,这个例子完全错了,这家伙可以给我一个更正吗?
所以这是我的代码:
private async void DoHardStuffAsync()
{
var result = DoHardStuff();
var secondResult = DoHardStuff();
var thirdResult = DoHardStuff();
await Task.WhenAll(result, secondResult, thirdResult);
MessageBox.Show(result.Result + secondResult.Result + thirdResult.Result);
}
private Task<string> DoHardStuff()
{
return Task.Run(() =>
{
var time = DateTime.Now;
while (DateTime.Now.Subtract(time).Milliseconds < 900)
{ }
return "finished";
});
}
而且:
private async void DoHardStuffAsync()
{
var result = DoHardStuff();
var secondResult = DoHardStuff();
var thirdResult = DoHardStuff();
MessageBox.Show(await result + await secondResult + await thirdResult);
}
为什么异步!=并行?我应该使用什么异步以及我应该使用并行(例如任务,线程)?
答案 0 :(得分:3)
Parallelism和asynchrony是两种不同的并发形式。并行性使用多个线程(例如,用于CPU绑定的代码)。异步使用多个操作,但不一定是多个线程(例如,对于I / O绑定的代码)。
Task.Run
是这两个世界之间的桥梁。它启动(可能是CPU绑定的)代码在后台线程上运行,并返回一个允许调用线程异步处理该工作的任务。
虽然Task.Run
对于基本并行性是可行的,但如果你有真正的CPU限制工作要做,那么最好使用Parallel
或并行LINQ。
关于你的代码示例,它们都非常相似:启动了三个后台任务,并且调用线程异步等待它们全部完成。
第一个调用Task<T>.Result
,我不鼓励,因为如果有异常,Result
将异常包装在AggregateException
中,而await
直接引发异常。 AggregateException
使错误处理变得复杂。
第二个人在每个任务上单独调用await
,这是可以的,但IMO并不理想。我认为await Task.WhenAll(..)
方法具有更清晰的意图(而且它的效率也更高一些)。
所以,我建议结合这些方法:
private async Task DoHardStuffAsync()
{
var result = DoHardStuff();
var secondResult = DoHardStuff();
var thirdResult = DoHardStuff();
await Task.WhenAll(result, secondResult, thirdResult);
MessageBox.Show(await result + await secondResult + await thirdResult);
}
我还将返回类型更改为Task
。作为一般规则,您应avoid async void
,正如我在MSDN文章中所描述的那样。
DoHardStuff
的实施也有点可疑。通常,您应该使用Task.Run
调用方法,而不是方法的实现。我有一个blog post详细介绍了这个主题。
答案 1 :(得分:0)
这些方法的实用性类似。但是,您对 Task.Result 的调用在我看来不同。这假设操作已完成并获得任务结果。这样做是非常危险的,因为它可能会爆炸,你最好使用 await 。