【问题标题】:TaskScheduler.Current and TaskScheduler.FromCurrentSynchronizationContext() difference?TaskScheduler.Current 和 TaskScheduler.FromCurrentSynchronizationContext() 的区别?
【发布时间】:2013-04-16 08:23:32
【问题描述】:

我有一个从数据库获取产品的任务,以及操作一些 UI 修改的 ContinueWith 操作,因此我遇到了问题,因为任务创建了一个新线程,并且 UI 修改不是在 UI 线程中执行的。

我尝试使用此修复:

var currentScheduler = TaskScheduler.Current;

Task.Factory.StartNew(() =>
{    
    // get products   
}).ContinueWith((x) => handleProductsArrived(x.Result, x.Exception), currentScheduler);

但它根本不起作用。我检查了一下,ContinueWith 没有在 currentScheduler 的线程中执行,而是在另一个线程中执行。

我发现了这个方法:

Task.Factory.StartNew(() =>
{
    // get products
}).ContinueWith((x) => handleProductsArrived(x.Result, x.Exception), TaskScheduler.FromCurrentSynchronizationContext());

它有效。那么有什么区别呢?为什么我的第一个代码不起作用? 谢谢!

【问题讨论】:

    标签: c# task scheduler


    【解决方案1】:

    来自TaskScheduler.Current 的文档:

    当不在任务中调用时,Current 将返回默认调度程序。

    然后来自Task Schedulers documentation

    Task Parallel Library 和 PLINQ 的默认调度程序使用 .NET Framework ThreadPool 来排队和执行工作。

    因此,如果您在不参与任务时使用TaskScheduler.Current,您将获得一个使用线程池的调度程序。

    如果您调用 TaskScheduler.FromCurrentSynchronizationContext(),您将获得一个当前的 synchronization context - 在 Windows 窗体或 WPF(当从 UI 线程调用时)是在相关 UI 线程上安排工作的上下文。

    这就是第一个代码不起作用的原因:它在线程池线程上执行了您的延续。您的第二个代码在 UI 线程上执行了延续。

    请注意,如果您可以使用 C# 5 和 async/await,那么所有这些都将处理得更简单

    【讨论】:

    • 当您不能像在 UI 组件的构造函数中那样使用 async/await 时,这很有用,对吧?
    • @Chin:我不会特别使用它——我通常有一个静态异步方法来完成工作,然后调用一个快速构造函数。
    • 您能详细说明一下吗?特别是我在这里还有另一个问题:stackoverflow.com/questions/31886276/… 有点相关
    • @Chin Constructor(){ DoHeavyWorkAndUpdate(); } private async void DoHeavyWorkAndUpdate(){ await Task.Run(()=>{... /*在这里计算,在后台线程上运行*/ }); /*这在主线程上运行*/ UpdateUI(); }
    猜你喜欢
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 2013-08-07
    • 2011-10-20
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多