任务和异步的区别 [英] Difference between Task and async
问题描述
C#提供了创建异步方法有两种方法:
C# provides two ways of creating asynchronous methods:
方法1:
static Task<string> MyAsyncTPL() {
Task<string> result = PerformWork();
return result.ContinueWith(t => MyContinuation());
}
方法2:
static async Task<string> MyAsync() {
string result = await PerformWork();
return MyContinuation();
}
上述两种方法都是异步并达到同样的事情。所以,我什么时候应该选择一种方法比其他?是否有使用一个比其他任何指导或优点?
Both the above methods are async and achieves the same thing. So, when should I choose one method over the other? Are there any guidelines or advantages of using one over the other?
推荐答案
我推荐你使用等待
,而不是 ContinueWith
。虽然 - 在一个较高的水平 - 他们是非常相似的,他们也有不同的默认行为
I recommend you use await
rather than ContinueWith
. While - at a high level - they are very similar, they also have different default behavior.
在使用 ContinueWith
,你选择一个低层的抽象。尤其是,这里有一些危险点,这就是为什么我不推荐使用 ContinueWith
,除非该方法的很简单的(或你的名字是斯蒂芬Toub):
When you use ContinueWith
, you are choosing a lower-level abstraction. In particular, here are some "danger points", and this is why I don't recommend using ContinueWith
unless the method is really simple (or your name is Stephen Toub):
- 从
提出异步任务异常
方法是放置在返回的任务;从非引发的异常。 -异步
方法是直接传播 -
计谋
在默认情况下将恢复在同一个背景下的异步
方法。这个背景是SynchronizationContext.Current
,除非它是空
,在这种情况下,它是TaskScheduler.Current
。这意味着,如果你调用MyAsync
在UI线程(或ASP.NET请求范围内),则MyContinuation
也将在UI线程(或在同一个ASP.NET请求上下文中)执行。我解释这更在我的博客。 - 您应该始终指定一个调度器
ContinueWith
;否则,它会拿起TaskScheduler.Current
,这可能会导致令人惊讶的行为。我描述了我的博客上详细这个问题。这文章是关于StartNew
;但ContinueWith
具有相同的非缺省默认的调度在该职位描述的问题。 -
计谋
将使用默认情况下未设置ContinueWith
适当的行为和优化标志。例如,使用DenyChildAttach
(保证异步任务不误用作并行任务)和ExecuteSynchronously
(优化)。
- Exceptions raised from
async Task
methods are placed on the returned task; exceptions raised from non-async
methods are propagated directly. await
will by default will resume theasync
method in the same "context". This "context" isSynchronizationContext.Current
unless it isnull
, in which case it isTaskScheduler.Current
. This means that if you callMyAsync
on a UI thread (or within an ASP.NET request context), thenMyContinuation
will also execute on the UI thread (or in that same ASP.NET request context). I explain this more on my blog.- You should always specify a scheduler for
ContinueWith
; otherwise, it will pick upTaskScheduler.Current
, which can cause surprising behavior. I describe this problem in detail on my blog. That post is aboutStartNew
; butContinueWith
has the same "non-default default scheduler" problem described in that post. await
uses appropriate behavior and optimization flags that are not set by default inContinueWith
. For example, it usesDenyChildAttach
(to ensure asynchronous tasks are not mistakenly used as parallel tasks) andExecuteSynchronously
(an optimization).
总之,使用 ContinueWith
异步任务的唯一原因是为了保存的非常的少量的时间和内存(通过避免异步
状态机的开销),作为交换你的code是的可读性和可维护性。
In short, the only reason to use ContinueWith
for asynchronous tasks is to save an extremely small amount of time and memory (by avoiding the async
state machine overhead), and in exchange your code is less readable and maintainable.
通过一个非常简单的例子,你可能会侥幸成功;但随着全碟指出的,只要你有循环的 ContinueWith
code只是爆炸的复杂性。
With an extremely simple example, you might get away with it; but as Jon Skeet pointed out, as soon as you have loops the ContinueWith
code simply explodes in complexity.
这篇关于任务和异步的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!