我开始在.Net WPF应用程序中使用await / async机制。
在我的ViewModel中,我在服务上调用异步方法。
我的问题是:
更好吗?return await Task.Run(()=>{...});
Task.Run
?以示例:
1)
public class Service:IService{
public async Task<SomeResult>(SomeParameter parameter){
return await Task.Run(()=>{
CopyStuff(parameter.A);
UpgradeStuff(parameter.B);
return ReloadStuff(parameter.C)
});
}
private void CopyStuff(ParamA parameter){
...//Some long operation that will mainly wait on the disk
}
private void UpgradeStuff(ParamB parameter){
...//Some long operation that should not block the GUI thread
}
public SomeResult ReloadStuff(ParamC parameter){
return ...;//Some long operation that relaunch some services and return their successs
}
}
2)
public class Service:IService{
public async Task<SomeResult>(SomeParameter parameter){
await CopyStuff(parameter.A);
await UpgradeStuff(parameter.B);
return await ReloadStuff(parameter.C)
}
private async Task CopyStuff(ParamA parameter){
return await Task.Run(()=>{...});//Some long operation that will mainly wait on the disk
}
private async Task UpgradeStuff(ParamB parameter){
return await Task.Run(()=>{...});//Some long operation that should not block the GUI thread
}
public async Task<SomeResult> ReloadStuff(ParamC parameter){
return await Task.Run(()=>{return ...});//Some long operation that relaunch some services and return their successs
}
}
我可以看到两种方法的优点:
答案 0 :(得分:9)
选择哪个选项?
我不会同时使用您的选项,它们都会创建一个误导性API ,每个使用您服务的人都会认为他使用的是异步方法,但事实是,在假签名后面方法实际上根本不是异步的
您的服务只是将工作推送到另一个ThreadPool
线程,该线程将在方法执行期间被阻止。
虽然在客户端使用此原则在服务器端听起来不那么糟糕,但这确实会损害您的可扩展性。
Stephen Cleary说:
在方法的实现中不要使用Task.Run;相反,使用 Task.Run调用方法。
如果方法实际上是同步的,你不应该使用假异步签名包装你的服务方法,如果你不想在重方法执行时阻止UI线程,你应该使用Task.Run您正在从视图模型中调用服务方法。
我建议你在博客中阅读Stephen Cleary系列Task.Run Etiquette articles。
考虑对I / O操作使用异步方法
此外,我可以看到您的服务所做的工作不仅仅是CPU绑定的工作,如果是这样的话,如果您现在使用的同步有任何可用的话,您应该考虑使用内置的I / O异步API方法(例如{ {3}}),在这种情况下,您的方法将是真正的异步方法,而不是现在的假异步包装器。
如果你这样做,你的UI线程将不会阻塞I / O异步操作将执行,但如果仍然涉及大量的CPU绑定工作,你不想在CPU绑定工作执行期间阻止UI从视图模型调用服务方法时,仍然可以使用Task.Run(即使方法签名已经是异步签名)。
更多关于上述系列文章中同步和异步方法的混合。
在异步API方法中使用bult的另一个巨大优势是,如果该方法在执行异步I / O操作时Asynchronous File I/O任何ThreadPool
线程真正异步,并且{{1} {{1}线程可以自由地做任何其他工作
在服务器端使用异步编程时,这尤其(但不仅仅)很重要,它可以真正提高您的可扩展性。
异步和MVVM
最后一件事,如果您关注MVVM模式do not block,那么您可以使用它。