你必须把Task.Run放在一个方法来使其asynchronous?
我试图了解asynchronous以最简单的forms等待。 我想创build一个非常简单的方法,为了这个例子增加了两个数字,根本没有处理时间,这只是一个例子。
例1:
private async Task DoWork1Async() { int result = 1 + 2; }
例2:
private async Task DoWork2Async() { Task.Run( () => { int result = 1 + 2; }); }
如果我等待DoWork1Async()
将代码同步或asynchronous运行?
我是否需要用Task.Run
包装同步代码,使该方法等待和asynchronous,以便不阻止UI线程?
我试图找出如果我的方法是一个Task
或返回Task<T>
我是否需要用Task.Run
包装代码使其asynchronous。
愚蠢的问题,我敢肯定,但我看到网上的例子,人们正在等待的代码,没有任何asynchronous内,并没有包裹在Task.Run
或StartNew
。
首先,我们来澄清一些术语:“asynchronous”( async
)意味着它可能会在调用线程启动之前将控制权交回给调用线程。 在async
方法中,这些“收益”点是await
expression式。
这与“asynchronous”这个术语有很大不同,因为MSDN文档使用了多年(意思是“在后台线程上执行”)。
为了进一步混淆这个问题, async
和“等待”是截然不同的。 有一些async
方法的返回types不可等待,许多方法返回不是async
等待types。
足够的,他们不是 ; 这是他们是什么:
-
async
关键字允许使用asynchronous方法(即允许await
expression式)。async
方法可能会返回Task
,Task<T>
或(如果您必须)void
。 - 任何遵循某种模式的types都可以等待。 最常见的等待types是
Task
和Task<T>
。
所以,如果我们将你的问题重新定义为“如何在后台线程上运行一个可等待的操作”,答案就是使用Task.Run
:
private Task<int> DoWorkAsync() // No async because the method does not need await { return Task.Run(() => { return 1 + 2; }); }
(但这种模式是一个不好的方法,见下文)。
但是,如果你的问题是“如何创build一个async
方法,可以返回给调用者而不是阻塞”,答案是声明方法async
并使用await
的“屈服”点:
private async Task<int> GetWebPageHtmlSizeAsync() { var client = new HttpClient(); var html = await client.GetAsync("http://www.example.com/"); return html.Length; }
所以,事情的基本模式是让async
代码依赖于它的await
expression式中的“awaitable”。 这些“awaitables”可以是其他的async
方法,或者只是返回awaitable的常规方法。 返回Task
/ Task<T>
常规方法可以使用Task.Run
在后台线程上执行代码,或者更常见的是可以使用TaskCompletionSource<T>
或其一个快捷方式( TaskFactory.FromAsync
, Task.FromResult
等) 。 我不build议在Task.Run
包装整个方法; 同步方法应该有同步签名,它应该留给消费者是否应该包装在一个Task.Run
:
private int DoWork() { return 1 + 2; } private void MoreSynchronousProcessing() { // Execute it directly (synchronously), since we are also a synchronous method. var result = DoWork(); ... } private async Task DoVariousThingsFromTheUIThreadAsync() { // I have a bunch of async work to do, and I am executed on the UI thread. var result = await Task.Run(() => DoWork()); ... }
我的博客上有一个async
/ await
介绍 ; 最后是一些很好的后续资源。 MSDN文档async
也exception好。
在使用asynchronous装饰方法时要记住的最重要的事情之一是至less在方法内部有一个 等待操作符。 在你的例子中,我将使用TaskCompletionSource如下所示进行翻译 。
private Task<int> DoWorkAsync() { //create a task completion source //the type of the result value must be the same //as the type in the returning Task TaskCompletionSource<int> tcs = new TaskCompletionSource<int>(); Task.Run(() => { int result = 1 + 2; //set the result to TaskCompletionSource tcs.SetResult(result); }); //return the Task return tcs.Task; } private async void DoWork() { int result = await DoWorkAsync(); }
当您使用Task.Run运行一个方法时,Task从线程池中获取一个线程来运行该方法。 所以从UI线程的angular度来看,它是“asynchronous的”,因为它不会阻塞UI线程。这对桌面应用程序来说很好,因为通常不需要很multithreading来处理用户交互。
但是,对于Web应用程序,每个请求都由线程池线程提供服务,因此可以通过保存这些线程来增加活动请求的数量。 经常使用线程池线程来模拟asynchronous操作对于Web应用程序是不可扩展的。
真正的asynchronous不一定涉及使用线程的I / O操作,如文件/数据库访问等。你可以阅读这个来理解为什么I / O操作不需要线程。 http://blog.stephencleary.com/2013/11/there-is-no-thread.html
在你的简单例子中,这是一个纯粹的CPU边界计算,所以使用Task.Run是好的。
- 从.Net 4.0到4.5的redirect解决scheme – 如何重新调整NuGet包?
- 是否有可能等待一个事件,而不是另一个asynchronous方法?
- HttpClient.GetAsync与networking凭据
- 在.NET 4.0中创build一个可以与.NET 4.5中的“await”一起使用的asynchronous方法
- Catch-22防止通过WIF保证stream式TCP WCF服务的安全 毁了我的圣诞节,心理健康
- HttpClient和HttpClientHandler必须被丢弃吗?
- Task <int>如何成为一个int?
- SqlDependency丢失订阅随着时间的推移
- 使用ConfigureAwait(false)和Task.Run之间有什么区别?