JuP*_*JuP 6 c# asynchronous task task-parallel-library
我已经阅读了很多关于异步编程的文章,但我不确定其中的一件事.我有第三方winrt库,用C++编写,我想包装它.所以现在我有:
public Task LoginAsync(){
return Task.Run(winrtLibrary.Login();)
}
Run Code Online (Sandbox Code Playgroud)
根据Stephen Cleary和Stephen Toub的博客,这不是一个好的解决方案.但是当我同步使用该方法时,我的UI将无法响应并将被阻止.是否更好地同步公开服务方法并在UI中使用Task.Run?
斯蒂芬·托布的意思是什么
\n\n\n\n\n在方法的实现中不要使用Task.Run;相反,使用 Task.Run 来调用该方法
\n
您不应该使用Task.Run异步方法(返回方法)来隐藏 CPU 密集型工作Task。如果您需要包装外部代码,请将其隐藏在反映此代码功能的接口后面。任何异步 I/O 都可以(并且应该)作为Task返回方法公开,并且 CPU 密集型工作必须使用正确的 API 公开。让代码的使用者自己决定如何使用该代码。当您碰巧也被消费者使用时,请使用它Task.Run来运行您的同步代码(现在通过接口包装和公开),很明显您正在卸载 CPU 密集型工作。例如,在 UI 应用程序中,您应该调用Task.RunUI 层(而不是深入 BL 甚至 DA 层),很明显,UI 卸载了一些 CPU 密集型工作。
\n\n\n你为什么认为我不应该在 BL 中调用 Task.Run ?如果我有 ViewModel,它引用 BL 并引用 BL 服务层(在我的情况下是包装器)怎么办?
\n
我认为方法签名应该准确反映该方法的作用。\n我能做的就是将您重定向回Cleary 的文章:
\n\n\n\n\n当开发人员在 API winrtLibrary.Login() 和 winrtLibrary.LoginAsync() 中看到两个方法时,约定是它们代表自然异步操作。换句话说,开发人员期望 winrtLibrary.LoginAsync() 是 \xe2\x80\x9cnatural\xe2\x80\x9d 实现,而 winrtLibrary.Login() 本质上是该操作的同步(阻塞)等效项。该 API 意味着 winrtLibrary.Login 在某个时刻会让调用线程进入等待状态,因为它会阻止自然异步操作完成。
\n
如果您将方法签名为public Task OffloadLoginToTheThreadPool(). 但我认为(显然 Cleary 也是如此)简单地Task.Run从 UI(或控制器)调用的替代方法是一种更好的方法,并且它遵循干净代码的原则。