2013-04-01 50 views
1

我寫下面的代碼嘗試使用的TaskScheduler運行任務。 UpdateStatus函數中的任務內容需要在主線程上運行。但我只是得到輸出表明它在單獨的線程上運行。的TaskScheduler不要在主線程

這是什麼緣故任何想法?或在主線程上下文中從後臺線程寫入狀態的替代方法。

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

爲什麼代碼需要在主線程上運行? 'Console'是線程安全的,所以你可以在任何線程中使用它。 – svick

+2

控制檯模式應用程序沒有能夠在特定線程上運行代碼的同步提供程序。這通常是一件非常平凡的事情,它需要目標線程進行合作。它必須爲[生產者/消費者問題](http://en.wikipedia.org/wiki/Producer-consumer_problem)提供解決方案。像任何GUI應用程序一樣。否則稱爲「泵送消息循環」。 –

+0

@svick這只是我的問題的一個演示,實際上我正在寫powershell cmdlet,其中'WriteObject'確實需要在特定的上下文中。 – Jackie

回答

0

你沒有解釋究竟是你想這樣做,因此很難爲您推薦最好的行動過程。

您當前的代碼不起作用,因爲SynchronizationContext你創建實際上並沒有做任何的同步。 (和你的主線程也被阻止在Wait()調用,因此沒有別的可以在其上運行。)

可能是正確同步到主線程(如the one from Nito AsyncEx)使用的同步環境,但我不當然,這是你案例中最好的方式。

我認爲更好的辦法是使用使用BlockingCollection生產者/消費者模式。您的Task s將添加項目,並且您的主線程將從那裏拿走它們並使用WriteObject()將它們發送到管道。

+0

thx您的建議,我會使用'BlockingCollection' – Jackie

1

默認的SynchronizationContext(您正在使用),不會讓你的主線程。請參閱Why SynchronizationContext does not work properly?

由於svick提到,你的情況(控制檯應用程序),通常不需要一個主線程的概念。

相關問題