使用Task.Run进行服务中的同步方法

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?

sha*_*y__ 4

斯蒂芬·托布的意思是什么

\n\n
\n

在方法的实现中不要使用Task.Run;相反,使用 Task.Run 来调用该方法

\n
\n\n

您不应该使用Task.Run异步方法(返回方法)来隐藏 CPU 密集型工作Task。如果您需要包装外部代码,请将其隐藏在反映此代码功能的接口后面。任何异步 I/O 都可以(并且应该)作为Task返回方法公开,并且 CPU 密集型工作必须使用正确的 API 公开。让代码的使用者自己决定如何使用该代码。当您碰巧也被消费者使用时,请使用它Task.Run来运行您的同步代码(现在通过接口包装和公开),很明显您正在卸载 CPU 密集型工作。例如,在 UI 应用程序中,您应该调用Task.RunUI 层(而不是深入 BL 甚至 DA 层),很明显,UI 卸载了一些 CPU 密集型工作。

\n\n
\n\n
\n

你为什么认为我不应该在 BL 中调用 Task.Run ?如果我有 ViewModel,它引用 BL 并引用 BL 服务层(在我的情况下是包装器)怎么办?

\n
\n\n

我认为方法签名应该准确反映该方法的作用。\n我能做的就是将您重定向回Cleary 的文章

\n\n
\n

当开发人员在 API winrtLibrary.Login() 和 winrtLibrary.LoginAsync() 中看到两个方法时,约定是它们代表自然异步操作。换句话说,开发人员期望 winrtLibrary.LoginAsync() 是 \xe2\x80\x9cnatural\xe2\x80\x9d 实现,而 winrtLibrary.Login() 本质上是该操作的同步(阻塞)等效项。该 API 意味着 winrtLibrary.Login 在某个时刻会让调用线程进入等待状态,因为它会阻止自然异步操作完成。

\n
\n\n

如果您将方法签名为public Task OffloadLoginToTheThreadPool(). 但我认为(显然 Cleary 也是如此)简单地Task.Run从 UI(或控制器)调用的替代方法是一种更好的方法,并且它遵循干净代码的原则。

\n