2017-01-23 6 views
0

Supersocketを使用していた古いプロジェクトを古いC++サーバーに更新しました。最後のバージョン(0.7.0 => 0.8.0.8)で再接続しようとしたときに例外が発生しました(ソケットが別のスレッドで開かれたと表示されます)タスクをエンキューするクラスが必要です再接続)し、それらをspedicificスレッドで実行します。特定のスレッドで実行するエンコーディングタスク

私はthisアプローチを見てきましたが、私は例外

ExecuteTask may not be called for a task which was previously queued to a different TaskScheduler. 

は、ここで私は

public class SameThreadTaskScheduler : TaskScheduler, IDisposable 
{ 
    #region publics 
    public SameThreadTaskScheduler(string name) 
    { 
     scheduledTasks = new Queue<Task>(); 
     threadName = name; 
    } 
    public override int MaximumConcurrencyLevel => 1; 

    public void Dispose() 
    { 
     lock (scheduledTasks) 
     { 
      quit = true; 
      Monitor.PulseAll(scheduledTasks); 
     } 
    } 
    #endregion 

    #region protected overrides 
    protected override IEnumerable<System.Threading.Tasks.Task> GetScheduledTasks() 
    { 
     lock (scheduledTasks) 
     { 
      return scheduledTasks.ToList(); 
     } 
    } 

    protected override void QueueTask(Task task) 
    { 
     if (myThread == null) 
      myThread = StartThread(threadName); 
     if (!myThread.IsAlive) 
      throw new ObjectDisposedException("My thread is not alive, so this object has been disposed!"); 
     lock (scheduledTasks) 
     { 
      scheduledTasks.Enqueue(task); 
      Monitor.PulseAll(scheduledTasks); 
     } 
    } 

    public void Queue(Task task) 
    { 
     QueueTask(task); 
    } 


    protected override bool TryExecuteTaskInline(Task task, bool task_was_previously_queued) 
    { 
     return false; 
    } 
    #endregion 

    private readonly Queue<System.Threading.Tasks.Task> scheduledTasks; 
    private Thread myThread; 
    private readonly string threadName; 
    private bool quit; 

    private Thread StartThread(string name) 
    { 
     var t = new Thread(MyThread) { Name = name }; 
     using (var start = new Barrier(2)) 
     { 
      t.Start(start); 
      ReachBarrier(start); 
     } 
     return t; 
    } 
    private void MyThread(object o) 
    { 
     Task tsk; 
     lock (scheduledTasks) 
     { 
      //When reaches the barrier, we know it holds the lock. 
      // 
      //So there is no Pulse call can trigger until 
      //this thread starts to wait for signals. 
      // 
      //It is important not to call StartThread within a lock. 
      //Otherwise, deadlock! 
      ReachBarrier(o as Barrier); 
      tsk = WaitAndDequeueTask(); 
     } 
     for (;;) 
     { 
      if (tsk == null) 
       break; 
      TryExecuteTask(tsk); 
      lock (scheduledTasks) 
      { 
       tsk = WaitAndDequeueTask(); 
      } 
     } 
    } 
    private Task WaitAndDequeueTask() 
    { 
     while (!scheduledTasks.Any() && !quit) 
      Monitor.Wait(scheduledTasks); 
     return quit ? null : scheduledTasks.Dequeue(); 
    } 

    private static void ReachBarrier(Barrier b) 
    { 
     if (b != null) 
      b.SignalAndWait(); 
    } 
} 

上記のリンクから撮影したクラスは、ここでどのようにだのGotとして作成したタスクを実行しようとすると、私はその仕事を呼びます

public void RegisterServers() 
    { 

     sameThreadTaskScheduler.Queue(new Task(() => 
      { 
       ...something 
      })); 

何が悪いのですか? ありがとう

+0

この 'Queue'メソッドの代わりに、タスクスケジューラで' Task.Start(TaskScheduler) '、または' Task.Factory.StartNew'を使ってみてください。 – acelent

答えて

0

TaskSchedulerにバインドするタスクを開始する必要があります。あなたのコードでは、タスクを手作業でキューイングしています。逆に実行すると、タスクスケジューラにバインドされず、TryExecuteTaskはそのエラーで失敗します。実際のTaskSchedulernullとは異なり、説明はかなりわかりにくいです。

実行せずに作成したタスクの場合、Task.RunSynchronouslyTask.Startの過負荷はTaskSchedulerになります。

自動的に実行を開始するタスクの場合、とTaskFactory<TResult>.StartNewのオーバーロードがTaskSchedulerになります。

継続タスクについては、TaskSchedulerを取るTask.ContinueWithTask<TResult>.ContinueWithTaskFactory.ContinueWhenAllTaskFactory.ContinueWhenAnyのオーバーロードがあります。

タスクスケジューラを使用しないオーバーロードは、TaskScheduler.Currentを指定するのと同じです。 TaskFactoryの場合、これはデフォルトのTask.Factory、またはファクトリのメソッドが呼び出された時点でタスクスケジューラなしで作成されたものの場合はtrueです。それ以外の場合は、ファクトリのタスクスケジューラが使用されます。


常にTaskScheduler.Defaultを使用Task.Run新しいのオーバーロードとは対照的。ほとんどの経験豊富な方々によれば、スレッドプールスケジューラは、スレッドバインドの可能性があるTaskScheduler.Currentよりもデフォルトとして頻繁に必要ですが、既存のAPIの契約を変更するには遅すぎます。

関連する問題