gpt4 book ai didi

c# - 响应任务完成 : `.ContinueWith()` vs `GetAwaiter().OnCompleted()`

转载 作者:行者123 更新时间:2023-12-03 17:41:18 26 4
gpt4 key购买 nike

假设我有一个 Task 生成 int ,以及接受 int 的回调:

Task<int> task = ...;
Action<int> f = ...;

现在我想设置它,以便一旦任务完成并返回其整数结果,callfack f将使用该整数调用 - 不需要主线程等待任务完成:
  • 据我了解,对此的典型解决方案是 Task.ContinueWith 方法:

    task.ContinueWith(t => f(t.Result));
  • 但是,您也可以获得 TaskAwaiter 对于任务,并使用其类似事件的界面:

    TaskAwaiter<int> awaiter = task.GetAwaiter();
    awaiter.OnCompleted(() => f(awaiter.GetResult()));

  • 现在,我意识到 TaskAwaiter不打算在应用程序代码中普遍使用,主要由 await 内部使用。关键词。
    但是为了加深我对TPL的理解,我想知道:

    解决方案(1)和(2)之间有什么实际区别吗?

    例如,
  • ...关于回调将在哪个线程上调用?
  • ...关于在任务或回调中抛出异常时会发生什么?
  • ……还有其他副作用吗?
  • 最佳答案

    一个区别是

    task.ContinueWith(t => f(t.Result));

    不会捕获当前的同步上下文,例如,在 UI 应用程序中 - 回调将在线程池线程上执行。尽管
    TaskAwaiter<int> awaiter = task.GetAwaiter();
    awaiter.OnCompleted(() => f(awaiter.GetResult()));

    将捕获同步上下文,并在 UI 线程上执行回调。

    当然你也可以用 ContinueWith 做同样的事情:
    task.ContinueWith(r => f(r.Result), TaskScheduler.FromCurrentSynchronizationContext());

    但这不是你使用的问题。因此,您的问题中提供的方法至少在这方面有所不同。

    异常表示也有区别,访问 Task.Result如果任务出错将抛出 AggregateException (有一个或多个异常作为内部异常),同时访问 awaiter.GetResult()不会在 AggregateException 中包装抛出的异常并将按原样重新抛出它(并且如果有多个异常,例如来自 Task.WhenAll - 除一个之外的所有异常都将被忽略,并且只会抛出一个)。

    关于c# - 响应任务完成 : `.ContinueWith()` vs `GetAwaiter().OnCompleted()` ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49921297/

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