5

複数のタスクを作成する並行ソフトウェアを作成する必要があり、すべてのタスクは別のタスクを生成できます(別のタスクも生成できます...)。

起動タスクがブロックされているメソッドへの呼び出しが必要です。すべてのタスクとサブタスクが完了する前に戻りません。

このプロパティがあることは知っていTaskCreationOptions.AttachedToParentますが、適合しないと思います:

サーバーには少なくとも8つのコアがあり、各タスクは2〜3のサブタスクを作成するため、AttachedToParentオプションを設定すると、最初のサブタスクの3つのタスクの前に2番目のサブタスクが開始されないという印象があります終了します。したがって、ここではマルチタスクを制限します。

したがって、このプロセス ツリーでは次のようになります。

ここに画像の説明を入力

スレッドを起動するたびに AttachedToParent プロパティを設定すると、E、F、G が終了する前に B が終了しないため、B が終了する前に C が開始され、アクティブなスレッドが 8 つではなく 3 つしかないという印象があります。私は持てます。

AttachedToParent プロパティを配置しない場合、A は非常に高速に終了して戻ります。

では、このオプションを設定しない場合、8 コアを常に完全に使用するにはどうすればよいでしょうか?

4

3 に答える 3

2

TaskCreationOptions.AttachedToParent、他のサブタスクの開始を妨げませんが、親タスク自体の終了を防ぎます。したがって、E、F、および G が AttachedToParent で開始された場合、3 つすべてが終了するまで、B には終了フラグが立てられません。だから、あなたが望むようにすべきです。

ソース(受け入れられた回答内)。

于 2012-07-05T11:07:50.070 に答える
2

Me.Name が述べAttachedToParentたように、あなたの印象に従って動作しません。この場合は良い選択だと思います。

ただし、何らかの理由でそれを使用したくない場合は、すべての子タスクが終了するまで待つことができますTask.WaitAll(). ただし、それらすべてをコレクションに含める必要があります。

Task.WaitAll()Taskすべての が終了するまで現在のスレッドをブロックします。それを望まず、.Net 4.5 を使用している場合は、 を使用できます。これは、指定されたすべてのsが終了したときに終了Task.WhenAll()する単一を返します。TaskTask

于 2012-07-05T11:45:01.010 に答える
1

TaskFactory次の例のようにオプションを作成できます。

Task parent = new Task(() => { 
var cts = new CancellationTokenSource(); 
var tf = new TaskFactory<Int32>(cts.Token,  
                                        TaskCreationOptions.AttachedToParent,  
                                        TaskContinuationOptions.ExecuteSynchronously,  
TaskScheduler.Default); 

 // This tasks creates and starts 3 child tasks 
 var childTasks = new[] { 
       tf.StartNew(() => Sum(cts.Token, 10000)), 
       tf.StartNew(() => Sum(cts.Token, 20000)), 
       tf.StartNew(() => Sum(cts.Token, Int32.MaxValue))  // Too big, throws Overflow
 }; 

// If any of the child tasks throw, cancel the rest of them 
for (Int32 task = 0; task <childTasks.Length; task++) 
  childTasks[task].ContinueWith( 
     t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted); 

// When all children are done, get the maximum value returned from the  
// non-faulting/canceled tasks. Then pass the maximum value to another  
// task which displays the maximum result 
tf.ContinueWhenAll( 
   childTasks,  
   completedTasks => completedTasks.Where( 
     t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result), CancellationToken.None) 
   .ContinueWith(t =>Console.WriteLine("The maximum is: " + t.Result), 
      TaskContinuationOptions.ExecuteSynchronously); 
}); 

// When the children are done, show any unhandled exceptions too 
parent.ContinueWith(p => { 
    // I put all this text in a StringBuilder and call Console.WriteLine just once  
    // because this task could execute concurrently with the task above & I don't  
    // want the tasks' output interspersed 
    StringBuildersb = new StringBuilder( 
                      "The following exception(s) occurred:" + Environment.NewLine); 

    foreach (var e in p.Exception.Flatten().InnerExceptions)  
         sb.AppendLine("   "+ e.GetType().ToString()); 

    Console.WriteLine(sb.ToString()); 
  }, TaskContinuationOptions.OnlyOnFaulted);

  // Start the parent Task so it can start its children 
  parent.Start();
于 2012-07-05T16:52:37.150 に答える