1

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

2 に答える 2

1

デフォルトの SynchronizationContext (使用している) では、メイン スレッドにアクセスできません。SynchronizationContext が正しく機能しない理由を参照してください。.

svick が言及しているように、あなたの場合 (コンソール アプリケーション) では、通常、メイン スレッドの概念は必要ありません。

于 2013-04-01T14:25:45.097 に答える
0

何をしようとしているのかを正確に説明していないため、最善の行動方針についてアドバイスすることは困難です.

SynchronizationContext作成している は実際には同期を行わないため、現在のコードは機能しません。(また、メイン スレッドもWait()呼び出し時にブロックされるため、他に何も実行できません。)

メインスレッドに適切に同期する同期コンテキスト( Nito AsyncEx のものなど)を使用できますが、それがあなたの場合に最適な方法であるかどうかはわかりません。

より良いアプローチは、を使用してプロデューサー/コンシューマー パターンを使用することだと思いますBlockingCollection。あなたTaskの s はそれに項目を追加し、メインスレッドはそこからそれらを取得し、 を使用してパイプラインに送信しますWriteObject()

于 2013-04-01T16:31:19.517 に答える