c# – 对任务完成做出反应:`.ContinueWith()`vs`GetAwaiter().OnCompleted()`

c# – 对任务完成做出反应:`.ContinueWith()`vs`GetAwaiter().OnCompleted()`,第1张

概述假设我有一个生成int的 Task,以及一个接受int的回调: Task<int> task = ...;Action<int> f = ...; 现在我想设置它,以便一旦任务完成并返回其整数结果,将使用该整数调用callfack f – 无需主线程等待任务完成: >据我了解,典型的解决方案是Task.ContinueWith方法: task.ContinueWith(t => f(t.Resu 假设我有一个生成int的 @L_404_0@,以及一个接受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()`全部内容,希望文章能够帮你解决c# – 对任务完成做出反应:`.ContinueWith()`vs`GetAwaiter().OnCompleted()`所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1233143.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-06
下一篇2022-06-06

发表评论

登录后才能评论

评论列表(0条)

    保存