简体   繁体   English

TaskScheduler不在主线程上运行任务

[英]TaskScheduler do not run task on main thread

I write following code to try using TaskScheduler. 我编写以下代码尝试使用TaskScheduler。 Task content within the UpdateStatus function need to be run on the main thread. UpdateStatus函数中的任务内容需要在主线程上运行。 But I just get the output indicate that it's running on separate thread. 但是我只得到输出指示它正在单独的线程上运行。

Any ideas about the reason? 关于原因有什么想法吗? or alternative method of writing status from background thread in main thread context. 或在主线程上下文中从后台线程写入状态的替代方法。

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();
    }
  }
}

The Default SynchronizationContext (which you are using), doesn't get you to the main thread. Default SynchronizationContext(您正在使用)不会使您进入主线程。 See Why SynchronizationContext does not work properly? 请参见为什么SynchronizationContext无法正常工作? .

As svick mentions, in your case (a Console application), there is usually no need for the concept of a main thread. 就像svick提到的,在您的情况下(控制台应用程序),通常不需要主线程的概念。

You didn't explain what exactly are you trying to do, so it's hard to advise you on the best course of action. 您没有解释您到底想做什么,因此很难为您提供最佳行动建议。

Your current code doesn't work, because the SynchronizationContext you're creating doesn't actually do any synchronization. 您当前的代码不起作用,因为您正在创建的SynchronizationContext实际上并未进行任何同步。 (And your main thread is also blocked on the Wait() call, so nothing else can run on it.) (并且您的主线程在Wait()调用上也被阻塞,因此其他任何线程都无法在其上运行。)

You could use synchronization context that synchronizes properly to the main thread (like the one from Nito AsyncEx ), but I'm not sure that's the best way in your case. 可以使用可以与主线程正确同步的同步上下文(例如Nito AsyncEx中的那个 ),但是我不确定这是否是您的最佳方法。

I think a better approach would be to use the producer/consumer pattern using BlockingCollection . 我认为更好的方法是使用BlockingCollection的生产者/消费者模式。 Your Task s would add items to it and your main thread would take them from there and send them to the pipeline using WriteObject() . 您的Task会向其中添加项目,而您的主线程会从那里带走它们,并使用WriteObject()将它们发送到管道中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM