TaskScheduler不在主线程上运行任务

时间:2013-04-01 05:39:41

标签: .net task-parallel-library

我编写以下代码以尝试使用TaskScheduler。 UpdateStatus函数中的任务内容需要在主线程上运行。但我只是得到输出表明它在单独的线程上运行。

有关原因的任何想法?或者在主线程上下文中从后台线程写入状态的替代方法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
  class Test
  {
    TaskScheduler scheduler;
    public void Run()
    {
      SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
      scheduler = TaskScheduler.FromCurrentSynchronizationContext();
      Console.WriteLine("Start on {0}", Thread.CurrentThread.ManagedThreadId);
      Task.Factory.StartNew(() =>
      {
        for (int i = 0; i < 10; i++)
        {
          Console.WriteLine("running on {0}", Thread.CurrentThread.ManagedThreadId);
          UpdateStatus(string.Format("Message {0}", i));
          Thread.Sleep(1000);
        }
      }).ContinueWith(_ =>
      {
        Console.WriteLine("complate");
        Console.WriteLine("running on {0}", Thread.CurrentThread.ManagedThreadId);
      }, new CancellationToken(), TaskContinuationOptions.None, scheduler).Wait();
    }

    private void UpdateStatus(string message)
    {
      Task.Factory.StartNew(() =>
      {
        Console.WriteLine("updating status on {0}", Thread.CurrentThread.ManagedThreadId);
        Console.WriteLine(message);
      }, new CancellationToken(), TaskCreationOptions.None, scheduler);
    }
  }

  class Program
  {
    public static void Main(string[] args)
    {
      var test = new Test();
      test.Run();
    }
  }
}

2 个答案:

答案 0 :(得分:1)

默认同步上下文(您正在使用),不会将您带到主线程。见Why SynchronizationContext does not work properly?

正如svick所提到的,在您的情况下(控制台应用程序),通常不需要主线程的概念。

答案 1 :(得分:0)

你没有解释你究竟想做什么,所以很难建议你采取最佳行动。

您当前的代码无效,因为您创建的SynchronizationContext实际上并未执行任何同步。 (并且你的主线程也在Wait()调用时被阻止,因此其他任何东西都无法运行。)

可以使用与主线程正确同步的同步上下文(如the one from Nito AsyncEx),但我不确定这是你案例的最佳方式。

我认为更好的方法是使用BlockingCollection使用生产者/消费者模式。您的Task会向其添加项目,主线程会从那里获取它们并使用WriteObject()将它们发送到管道。