2012-05-14 11 views
0

ParallelExetensionExtrasに同梱されているQueuedTaskSchedulerに問題がありますが、私の質問は待機中のタスク、タスクスケジューラ、およびスレッドリソースについてかなり一般的です。TPLのタスクを待機し、QueuedTaskScheduler(ParallelExtensionsExtra)の問題を解決する

待ちタスクがリソースを消費するように見えます。この例では、デフォルトのタスクスケジューラを使用しています。この例では、長時間実行されるタスクが1つあり、完了を待つタスクがいくつかあります以下の実行を保留中です。

すべてがうまくいきます。待機中のタスクが作業を開始し、待機時間中にリソースを解放して他のタスクも実行を開始することがわかります。

var taskScheduler = TaskScheduler.Default;//ts.ActivateNewQueue(0); 

var longRunningTask = Task.Factory.StartNew(() => Thread.Sleep(Int32.MaxValue), CancellationToken.None, TaskCreationOptions.None, taskScheduler); 

Task.Factory.StartNew(() => 
{ 
    Console.WriteLine("Hi from waiting task"); 
    longRunningTask.Wait(); 
}, CancellationToken.None, TaskCreationOptions.None, taskScheduler); 
Task.Factory.StartNew(() => 
{ 
    Console.WriteLine("Hi from waiting task"); 
    longRunningTask.Wait(); 
}, CancellationToken.None, TaskCreationOptions.None, taskScheduler); 
Task.Factory.StartNew(() => 
{ 
    Console.WriteLine("Hi from waiting task"); 
    longRunningTask.Wait(); 
}, CancellationToken.None, TaskCreationOptions.None, taskScheduler); 

Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler); 
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler); 
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler); 
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler); 
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler); 
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler); 
Task.Factory.StartNew(() => Console.WriteLine("Hi"), CancellationToken.None, TaskCreationOptions.None, taskScheduler); 

私はこれを行うには、最初の2行に変更した場合:

var ts = new QueuedTaskScheduler(); 
var taskScheduler = ts.ActivateNewQueue(0); 

意味を、他のタスクを実行するためのリソースを取得していないだけで決して、1つのキューでQueuedTaskSchedulerを定義し、同じコードを実行します。

私の質問は、以前に誰かが突っ込んできた場合、誰かがタスクスケジューラを変更して待機中のタスク用のリソースを解放する方法を知っているかどうかです。

+0

なぜこれらのタスクが最初の「タスク」を待っているのですか? – svick

答えて

0

QueuedTaskSchedulerは設計どおりに動作しています。問題は、デフォルトではEnvironment.ProcessorCountに設定されている固定最大同時実行レベルがあることです。

このため、デフォルトを変更しなかったと仮定した場合、4コアコンピュータで最大4つの実行タスクが発生します。

これを修正するには、(Defaultのような​​をサポートし、理想的に1、)異なるスケジューラの実行時間の長いタスクを実行するか、または単に最大値に極端な場合には、最大同時実行レベルを設定します。

var ts = new QueuedTaskScheduler(TaskScheduler.Default, int.MaxValue); 
+0

こんにちは、待っているタスクがリソースを消費するように設計されていますか?なぜこれはデフォルトのタスクスケジューラの動作ではありませんか? – Gilad

+0

私は、デフォルトのタスクスケジューラで同じコード(長い実行タスクで)をテストしていましたが、うまくいきました。カスタムタスクスケジューラの違いによって動作が異なるのは何ですか? – Gilad

+0

ああ、もう1つのコメント、最大並列度レベルでは、割り当てられるスレッドの数が決まります。多すぎるスレッドは解決策ではありません。実際には速度を上げるのではなく、速度を落とす可能性が高くなります。それをint.MaxValueに設定すると、OutOfMemoryExceptionが発生します - 私は誰も推測しないでしょう。 – Gilad