假设我有一个方法,该方法使用一些异步调用来运行连续的while循环
async Task MethodA(){
while(true){ perform async/await operations }
}
两者之间有什么区别?
Task.Run( () => MethodA(); }
Task.Run( async () => await MethodA(); }
如果有区别,什么时候比另一个有用?
答案 0 :(得分:1)
async () => await MethodA();
基本上是async void
,并且不会被观察
要了解这种效果,我们需要记住
async
方法 操作。当您调用async
方法时,它开始运行 同步地。如果该方法中没有任何
await
(或者如果所有 方法中的等待项中的已经存在的等待项 在等待时完成)然后该方法将运行 完全同步。但是,当方法遇到第一个
await
产生,async
方法返回。如果是async
返回Task
或Task<TResult>
的方法,此时的方法 点返回代表ask<TResult>
的Task或Tasync
方法的执行,调用者可以使用该任务等待 同步(例如Wait())或异步(例如await,ContinueWith) 使该方法异步完成。但是,在使用void方法的情况下,不会交出任何句柄。因此,异步void方法 通常被称为“忘了忘了”。
Id建议在async await
上浏览许多 Stephen Cleary 信息。这是一个开始
When correctly use Task.Run and when just async-await
Parallel先生的好文章 Stephen Toub
Potential pitfalls to avoid when passing around async lambdas
答案 1 :(得分:0)
根据斯蒂芬·克莱尔(Stephen Cleary)在答案https://stackoverflow.com/a/19098209/3107892中的回答以及他的链接博客文章,唯一的区别是第二个创建了状态机。在这里,您可以使用第一种情况,而没有任何缺点。
以下是您可以遵循的一些准则:
仅此而已,基于此处的另一个答案:
Task.Run(Func<Task>)
将在线程池中将函数的结果排队,并且当排队的任务完成(包括所有等待)时,结果函数将完成
Task.Run( MethodA );
会将方法转换为委托并将其传递。
Task.Run( () => MethodA() );
将创建一个隐藏方法,该方法将返回MethodA
的结果(此隐藏方法将转换为委托并继续传递)。
Task.Run( async () => await MethodA() );
将创建一个包含await的隐藏方法,但是如前所述,该方法将转换为状态机,最后将MethodA()
的结果包装到新的{{1 }}。
Task
完全不同,由于花括号,这将导致Task.Run(Action)
重载,在这种情况下,Task.Run( () => { MethodA(); } );
将继续执行此任务,直到遇到第一个未完成的任务等待,然后完成。此内部任务完成之后(内部等待之后)将不会受到此MethodA()
的监视,但是将继续在线程池上运行,并且如果引发异常,则可能导致应用程序崩溃。原因是Task.Run
返回的任务由于缺少关键字MethodA
而被忽略。
return
是对此异常的修复,将与所有其他示例一样工作。
答案 2 :(得分:-1)
有很大的不同。 MethodA()
返回Task
。如果您不等待该Task
的结果,那么处理将照常进行。
即
Task.Run( () => MethodA(); }
MethodA()
一旦在内部达到等待状态,就会返回Task
。 lambda现在已完成(它已调用MethodA()
并获得了返回值),因此Task.Run()
将其自身的任务标记为已完成,并且线程将被释放。
Task.Run( async () => await MethodA(); }
lambda是异步的,您正在等待MethodA()
的真实结果。由Task
返回的Task.Run()
在MethodA()完成之前不会完成。