[英]Using Task.Run for synchronous method in service
I've read a lot of articles about asynchronnous programming, but I'm not sure in one thing. 我已经阅读了很多有关异步编程的文章,但是我不确定一件事。 I have 3rd party winrt library, written in C++ and I want to wrapp it. 我有用C ++编写的3rd party winrt库,我想包装一下。 So now I have: 所以现在我有:
public Task LoginAsync(){
return Task.Run(winrtLibrary.Login();)
}
According Stephen Cleary and Stephen Toub blogs, it is not good solution. 根据Stephen Cleary和Stephen Toub的博客,这不是一个好的解决方案。 But when I use the method synchronously, my UI will not be responsive and will be blocked. 但是,当我同步使用该方法时,我的UI将不会响应,并且将被阻止。 Is it better to expose service method synchronously and in UI use Task.Run? 最好是同步公开服务方法并在UI中使用Task.Run吗?
What Stephen Toub means by Stephen Toub的意思是
do not use Task.Run in the implementation of the method; 在该方法的实现中不要使用Task.Run; instead, use Task.Run to call the method 而是使用Task.Run来调用该方法
Is that you shouldn't use Task.Run
to hide CPU bound work behind async methods ( Task
returning methods). 是您不应该使用Task.Run
将CPU绑定的工作隐藏在异步方法( Task
返回方法)之后。 If you need to wrap external code, hide it behind an interface which reflects what this code do. 如果需要包装外部代码,请将其隐藏在反映此代码功能的接口后面。 Any asynchronous I/O can (and should) be exposed as Task
returning methods, and CPU bound work must be exposed with the proper API. 任何异步I / O都可以(并且应该)作为Task
返回方法公开,并且必须使用适当的API公开与CPU绑定的工作。 Let the consumers of your code to decide for themselves how to use that code. 让您的代码使用者自行决定如何使用该代码。 When you happen to by the consumer too, use Task.Run
to run your synchronous code (now wrapped and exposed via interface) where it is very clear that you are offloading CPU bound work . 当用户碰巧遇到这种情况时,也可以使用Task.Run
运行您的同步代码(现在已经通过接口包装并公开)了,很明显,您正在卸载CPU绑定的工作 。 In UI apps, for example, you should call Task.Run
in your UI layer (and not deep down in your BL or even DA layers), where it is very clear that the UI offloads some CPU bound work. 例如,在UI应用程序中,应在UI层(而不是在BL层甚至DA层中)调用Task.Run
,这很明显,UI减轻了一些CPU限制的工作。
Why do you think, that I shouldn't call Task.Run in BL? 您为什么认为我不应该在BL中调用Task.Run? What if I have ViewModel, which references BL and BL references service layer (in my case is it wrapper). 如果我有ViewModel,该模型引用BL,而BL引用服务层(在我的情况下是包装),该怎么办?
I think that a method signature should reflect exactly what the method does. 我认为方法签名应准确反映该方法的作用。 The best I can do is to redirect you back to Cleary's article : 我能做的最好的就是将您重定向回Cleary的文章 :
When a developer sees two methods in an API winrtLibrary.Login() and winrtLibrary.LoginAsync(), the convention is that they represent a naturally-asynchronous operation . 当开发人员在API winrtLibrary.Login()和winrtLibrary.LoginAsync()中看到两个方法时, 约定是它们代表自然异步操作 。 In other words, the developer expects that winrtLibrary.LoginAsync() is the “natural” implementation and that winrtLibrary.Login() is essentially a synchronous (blocking) equivalent of that operation. 换句话说,开发人员期望winrtLibrary.LoginAsync()是“自然”的实现,并且winrtLibrary.Login()本质上是该操作的同步(阻塞)等效项。 That API implies that winrtLibrary.Login will at some point have the calling thread enter a wait state as it blocks for the naturally-asynchronous operation to complete. 该API表示winrtLibrary.Login会在某个时刻使调用线程进入等待状态,因为它阻塞了自然异步操作的完成。
You can still hide synchronous code behind async method and follow Cleary's rule of thumb, if you sign your method as public Task OffloadLoginToTheThreadPool()
. 如果您将方法签名为public Task OffloadLoginToTheThreadPool()
,则仍然可以将同步代码隐藏在async方法后面,并遵循Cleary的经验法则。 But I think (and apparently Cleary, too) that the alternative of simply calling Task.Run
from the UI (or Controller) is a much better approach, and it follows the principles of Clean Code. 但是我认为(而且显然也是Cleary),从UI(或控制器)简单调用Task.Run
的替代方法是一种更好的方法,它遵循了Clean Code的原理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.