gpt4 book ai didi

c# - 任务和异步任务之间的区别

转载 作者:可可西里 更新时间:2023-11-01 02:59:17 25 4
gpt4 key购买 nike

C# 提供了两种创建异步方法的方法:

任务():

static Task<string> MyAsyncTPL() {
Task<string> result = PerformWork();
return result.ContinueWith(t => MyContinuation());
}

异步任务():

static async Task<string> MyAsync() {
string result = await PerformWork();
return MyContinuation();
}

以上两种方法都是async 并且实现相同的目的。那么,我什么时候应该选择一种方法而不是另一种方法呢?使用其中一种优于另一种有什么指导方针或优势吗?

最佳答案

我建议您使用 await 而不是 ContinueWith。虽然 - 在高层次上 - 它们非常相似,但它们也有不同的默认行为。

当您使用 ContinueWith 时,您选择了较低级别的抽象。特别是,这里有一些“危险点”,这就是我不推荐使用 ContinueWith 的原因,除非该方法非常简单(或者你的名字是 Stephen Toub) :

  • async Task 方法引发的异常放在返回的任务上;从非 async 方法引发的异常将直接传播。
  • await 默认情况下会在相同的“上下文”中恢复 async 方法。此“上下文”为 SynchronizationContext.Current,除非它为 null,在这种情况下为 TaskScheduler.Current。这意味着如果您在 UI 线程上(或在 ASP.NET 请求上下文中)调用 MyAsync,则 MyContinuation 也会在 UI 线程上(或在同一个线程中)执行ASP.NET 请求上下文)。我再解释一下on my blog .
  • 您应该始终为 ContinueWith 指定一个调度程序;否则,它会选择 TaskScheduler.Current,这会导致令人惊讶的行为。我详细描述了这个问题on my blog .那篇文章是关于 StartNew 的;但是 ContinueWith 具有该帖子中描述的相同“非默认默认调度程序”问题。
  • await 使用适当的行为和优化标志,这些标志在 ContinueWith 中默认未设置。例如,它使用 DenyChildAttach(以确保异步任务不会被错误地用作并行任务)和 ExecuteSynchronously(一种优化)。

简而言之,对异步任务使用ContinueWith 的唯一原因是节省时间和内存(通过避免async 状态机开销),作为交换,您的代码可读性和可维护性较差。

用一个非常简单的例子,你可能会侥幸逃脱;但正如 Jon Skeet 指出的那样,一旦有了循环,ContinueWith 代码的复杂性就会爆炸。

关于c# - 任务和异步任务之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22997523/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com