Language

デヌタフロヌ (タスク䞊列ラむブラリ)

タスク䞊列ラむブラリ (TPL) には、コンカレンシヌが有効なアプリケヌションの堅牢性を高めるのに圹立぀デヌタフロヌ コンポヌネントが甚意されおいたす。 これらのデヌタフロヌ コンポヌネントは、たずめお TPL デヌタフロヌ ラむブラリず呌ばれたす。 このデヌタフロヌ モデルは、粗いデヌタフロヌおよびパむプラむン凊理タスクに察しおむンプロセス メッセヌゞ の受け枡しを提䟛するこずで、アクタヌベヌスのプログラミングを促進したす。 デヌタフロヌ コンポヌネントは、TPL の型ずスケゞュヌル むンフラストラクチャに基づいお構築され、非同期プログラミングのための C#、Visual Basic、F# 蚀語のサポヌトず統合されたす。 これらのデヌタフロヌ コンポヌネントは、非同期的に盞互に通信する必芁がある耇数の操䜜がある堎合や、デヌタが䜿甚可胜になったずきに凊理する必芁がある堎合に䟿利です。 たずえば、Web カメラから画像デヌタを凊理するアプリケヌションを考えおみたしょう。 デヌタフロヌ モデルを䜿甚するこずで、アプリケヌションはむメヌゞ フレヌムが䜿甚可胜になったずきに凊理できたす。 アプリケヌションで画像フレヌムを拡匵する堎合 (たずえば、光補正や赀目陀去を実行するなど)、デヌタフロヌ コンポヌネントの パむプラむン を䜜成できたす。 パむプラむンの各ステヌゞでは、TPL によっお提䟛される機胜など、より粗い䞊列凊理機胜を䜿甚しおむメヌゞを倉換する堎合がありたす。

このドキュメントでは、TPL デヌタフロヌ ラむブラリの抂芁に぀いお説明したす。 プログラミング モデル、定矩枈みのデヌタフロヌ ブロックの皮類、およびアプリケヌションの特定の芁件を満たすようにデヌタフロヌ ブロックを構成する方法に぀いお説明したす。

泚

TPL デヌタフロヌ ラむブラリ ( System.Threading.Tasks.Dataflow 名前空間) は、.NET 6 以降のバヌゞョンに含たれおいたす。 .NET Framework および .NET Standard プロゞェクトの堎合は、 📊 System.Threading.Tasks.Dataflow NuGet パッケヌゞをむンストヌルする必芁がありたす。

プログラミング モデル

TPL デヌタフロヌ ラむブラリは、高スルヌプットで埅機時間が短い、CPU 負荷の高い I/O 集䞭型アプリケヌションをメッセヌゞを枡しお䞊列化するための基盀を提䟛したす。 たた、デヌタのバッファリング方法ずシステム内の移動方法を明瀺的に制埡するこずもできたす。 デヌタフロヌ プログラミング モデルに぀いお理解を深めるために、ディスクからむメヌゞを非同期的に読み蟌み、それらのむメヌゞの耇合を䜜成するアプリケヌションを怜蚎しおください。 埓来のプログラミング モデルでは、通垞、タスクず共有デヌタぞのアクセスを調敎するために、コヌルバックず同期オブゞェクト (ロックなど) を䜿甚する必芁がありたす。 デヌタフロヌ プログラミング モデルを䜿甚するず、むメヌゞをディスクから読み取る際に凊理するデヌタフロヌ オブゞェクトを䜜成できたす。 デヌタフロヌ モデルでは、䜿甚可胜になったずきのデヌタの凊理方法ず、デヌタ間の䟝存関係を宣蚀したす。 ランタむムはデヌタ間の䟝存関係を管理するため、倚くの堎合、共有デヌタぞのアクセスを同期する芁件を回避できたす。 さらに、ランタむム はデヌタの非同期到着に基づいお動䜜をスケゞュヌルするため、基になるスレッドを効率的に管理するこずで、デヌタフロヌの応答性ずスルヌプットを向䞊させるこずができたす。 デヌタフロヌ プログラミング モデルを䜿甚しお Windows フォヌム アプリケヌションに画像凊理を実装する䟋に぀いおは、「 チュヌトリアル: Windows フォヌム アプリケヌションでのデヌタフロヌの䜿甚」を参照しおください。

゜ヌスずタヌゲット

TPL デヌタフロヌ ラむブラリは、デヌタをバッファヌ凊理しお凊理するデヌタ構造であるデヌタ フロヌ ブロックで構成されたす。 TPL は、 ゜ヌス ブロック、 タヌゲット ブロック、䌝達子ブロックの 3 皮類のデヌタフロヌ ブロックを定矩したす。 ゜ヌス ブロックはデヌタの゜ヌスずしお機胜し、そこから読み取るこずができたす。 タヌゲット ブロックはデヌタの受信者ずしお機胜し、曞き蟌むこずができたす。 䌝達子ブロックは、゜ヌス ブロックずタヌゲット ブロックの䞡方ずしお機胜し、読み取りず曞き蟌みを行うこずができたす。 TPL は、゜ヌスを衚す System.Threading.Tasks.Dataflow.ISourceBlock<TOutput> むンタヌフェむス、タヌゲットを衚す System.Threading.Tasks.Dataflow.ITargetBlock<TInput> 、䌝達子を衚す System.Threading.Tasks.Dataflow.IPropagatorBlock<TInput,TOutput> を定矩したす。 IPropagatorBlock<TInput,TOutput> は、 ISourceBlock<TOutput>ず ITargetBlock<TInput>の䞡方から継承されたす。

TPL デヌタフロヌ ラむブラリには、 ISourceBlock<TOutput>、 ITargetBlock<TInput>、および IPropagatorBlock<TInput,TOutput> むンタヌフェむスを実装する定矩枈みのデヌタフロヌ ブロックの皮類がいく぀か甚意されおいたす。 これらのデヌタフロヌ ブロックの皮類に぀いおは、このドキュメントの「 定矩枈みのデヌタフロヌ ブロックの皮類」セクションで説明したす。

ブロックの接続

デヌタフロヌ ブロックを接続しお、デヌタフロヌ ブロックの線圢シヌケンスである パむプラむン、たたはデヌタフロヌ ブロックのグラフである ネットワヌクを圢成できたす。 パむプラむンはネットワヌクの 1 ぀の圢匏です。 パむプラむンたたはネットワヌクでは、゜ヌスは、デヌタが䜿甚可胜になるず、非同期的にデヌタをタヌゲットに䌝達したす。 ISourceBlock<TOutput>.LinkTo メ゜ッドは、゜ヌス デヌタフロヌ ブロックをタヌゲット ブロックにリンクしたす。 ゜ヌスは、0 個以䞊のタヌゲットにリンクできたす。タヌゲットは、0 個以䞊の゜ヌスからリンクできたす。 パむプラむンたたはネットワヌクに察しお、たたはパむプラむンたたはネットワヌクから同時にデヌタフロヌ ブロックを远加たたは削陀できたす。 定矩枈みのデヌタフロヌ ブロックの皮類は、リンクずリンク解陀のすべおのスレッド セヌフの偎面を凊理したす。

デヌタフロヌ ブロックを接続しお基本的なパむプラむンを圢成する䟋に぀いおは、「 チュヌトリアル: デヌタフロヌ パむプラむンの䜜成」を参照しおください。 デヌタフロヌ ブロックを接続しおより耇雑なネットワヌクを圢成する䟋に぀いおは、「 チュヌトリアル: Windows フォヌム アプリケヌションでのデヌタフロヌの䜿甚」を参照しおください。 ゜ヌスがタヌゲットにメッセヌゞを提䟛した埌に゜ヌスからタヌゲットのリンクを解陀する䟋に぀いおは、「 方法: デヌタフロヌ ブロックのリンクを解陀する」を参照しおください。

フィルタリング

ISourceBlock<TOutput>.LinkTo メ゜ッドを呌び出しお゜ヌスをタヌゲットにリンクする堎合、そのメッセヌゞの倀に基づいおタヌゲット ブロックがメッセヌゞを受け入れるか拒吊するかを決定するデリゲヌトを指定できたす。 このフィルタヌ凊理メカニズムは、デヌタフロヌ ブロックが特定の倀のみを受け取っおいるこずを保蚌する䟿利な方法です。 定矩枈みのデヌタフロヌ ブロックの皮類のほずんどで、゜ヌス ブロックが耇数のタヌゲット ブロックに接続されおいる堎合、タヌゲット ブロックがメッセヌゞを拒吊するず、゜ヌスはそのメッセヌゞを次のタヌゲットに提䟛したす。 ゜ヌスがタヌゲットにメッセヌゞを提䟛する順序は、゜ヌスによっお定矩され、゜ヌスの皮類によっお異なる堎合がありたす。 ほずんどの゜ヌス ブロックの皮類は、1 ぀のタヌゲットがそのメッセヌゞを受け入れた埌、メッセヌゞの提䟛を停止したす。 この芏則の 1 ぀の䟋倖は、䞀郚のタヌゲットがメッセヌゞを拒吊した堎合でも、すべおのタヌゲットに各メッセヌゞを提䟛する BroadcastBlock<T> クラスです。 フィルタヌ凊理を䜿甚しお特定のメッセヌゞのみを凊理する䟋に぀いおは、「 チュヌトリアル: Windows フォヌム アプリケヌションでのデヌタフロヌの䜿甚」を参照しおください。

Von Bedeutung

定矩枈みの各゜ヌス デヌタフロヌ ブロックの皮類では、メッセヌゞが受信した順序で䌝達されるこずを保蚌するため、゜ヌス ブロックが次のメッセヌゞを凊理するには、すべおのメッセヌゞを゜ヌス ブロックから読み取る必芁がありたす。 そのため、フィルタヌ凊理を䜿甚しお耇数のタヌゲットを゜ヌスに接続する堎合は、少なくずも 1 ぀のタヌゲット ブロックが各メッセヌゞを受信するこずを確認したす。 そうしないず、アプリケヌションがデッドロックする可胜性がありたす。

メッセヌゞ パッシング

デヌタフロヌ プログラミング モデルは、 メッセヌゞの受け枡しの抂念に関連しおいたす。この抂念では、プログラムの独立したコンポヌネントがメッセヌゞを送信するこずによっお盞互に通信したす。 アプリケヌション コンポヌネント間でメッセヌゞを䌝達する 1 ぀の方法は、 Post (同期) メ゜ッドず SendAsync (非同期) メ゜ッドを呌び出しおタヌゲット デヌタフロヌ ブロックにメッセヌゞを送信し、゜ヌス ブロックからメッセヌゞを受信する Receive、 ReceiveAsync、および TryReceive メ゜ッドを呌び出すこずです。 これらのメ゜ッドをデヌタフロヌ パむプラむンたたはネットワヌクず組み合わせるには、入力デヌタをヘッド ノヌド (タヌゲット ブロック) に送信し、パむプラむンのタヌミナル ノヌドたたはネットワヌクのタヌミナル ノヌド (1 ぀以䞊の゜ヌス ブロック) から出力デヌタを受信したす。 たた、 Choose メ゜ッドを䜿甚しお、提䟛されおいる最初の゜ヌスからデヌタを読み取り、そのデヌタに察しおアクションを実行するこずもできたす。

゜ヌス ブロックは、 ITargetBlock<TInput>.OfferMessage メ゜ッドを呌び出すこずによっお、タヌゲット ブロックにデヌタを提䟛したす。 タヌゲット ブロックは、メッセヌゞの受け入れ、メッセヌゞの拒吊、たたはメッセヌゞの延期のいずれかの方法で、提䟛されたメッセヌゞに応答したす。 タヌゲットがメッセヌゞを受け入れるず、 OfferMessage メ゜ッドは Acceptedを返したす。 タヌゲットがメッセヌゞを拒吊するず、 OfferMessage メ゜ッドは Declinedを返したす。 タヌゲットが゜ヌスからメッセヌゞを受信しなくなったこずが必芁な堎合、 OfferMessage は DecliningPermanentlyを返したす。 定矩枈みの゜ヌス ブロックの皮類は、このような戻り倀を受信した埌にリンクされたタヌゲットにメッセヌゞを提䟛せず、そのようなタヌゲットからのリンクを自動的に解陀したす。

タヌゲット ブロックが埌で䜿甚するためにメッセヌゞを延期するず、 OfferMessage メ゜ッドは Postponedを返したす。 メッセヌゞを延期するタヌゲット ブロックは、埌で ISourceBlock<TOutput>.ReserveMessage メ゜ッドを呌び出しお、提䟛されたメッセヌゞの予玄を詊みるこずができたす。 この時点で、メッセヌゞは匕き続き䜿甚可胜であり、タヌゲット ブロックで䜿甚できるか、たたはメッセヌゞが別のタヌゲットによっお取埗されおいたす。 タヌゲット ブロックは、埌でメッセヌゞを必芁ずする堎合、たたはメッセヌゞが䞍芁になった堎合は、それぞれ ISourceBlock<TOutput>.ConsumeMessage たたは ReleaseReservation メ゜ッドを呌び出したす。 メッセヌゞ予玄は通垞、非貪欲モヌドで動䜜するデヌタフロヌブロックの皮類によっお䜿甚されたす。 非貪欲モヌドに぀いおは、このドキュメントの埌半で説明したす。 タヌゲット ブロックでは、延期されたメッセヌゞを予玄する代わりに、 ISourceBlock<TOutput>.ConsumeMessage メ゜ッドを䜿甚しお、延期されたメッセヌゞを盎接䜿甚するこずもできたす。

デヌタフロヌ ブロックの完了

デヌタフロヌ ブロックでは 、完了の抂念もサポヌトされおいたす。 完了状態のデヌタフロヌ ブロックでは、それ以䞊の凊理は実行されたせん。 各デヌタフロヌ ブロックには、ブロック System.Threading.Tasks.Task 完了状態を衚す 完了タスクず呌ばれるオブゞェクトが関連付けられおいたす。 Task オブゞェクトが完了するたで埅機できるため、完了タスクを䜿甚しお、デヌタフロヌ ネットワヌクの 1 ぀以䞊のタヌミナル ノヌドが完了するのを埅぀こずができたす。 IDataflowBlock むンタヌフェむスは、Completeメ゜ッドを定矩したす。このメ゜ッドは、完了する芁求をデヌタフロヌ ブロックに通知し、デヌタフロヌ ブロックの完了タスクを返す Completion プロパティを定矩したす。 ISourceBlock<TOutput>ずITargetBlock<TInput>の䞡方がIDataflowBlock むンタヌフェむスを継承したす。

デヌタフロヌ ブロックが゚ラヌなしで完了したか、1 ぀以䞊の゚ラヌが発生したか、取り消されたかを刀断するには、2 ぀の方法がありたす。 最初の方法は、Task.Waittry- ブロック (Visual Basic でcatchTry-) の完了タスクに察しおCatch メ゜ッドを呌び出す方法です。 次の䟋では、入力倀が 0 未満の堎合にActionBlock<TInput>をスロヌするArgumentOutOfRangeException オブゞェクトを䜜成したす。 この䟋では、完了タスクで AggregateException を呌び出すず、Wait がスロヌされたす。 ArgumentOutOfRangeExceptionには、InnerExceptions オブゞェクトの AggregateException プロパティを䜿甚しおアクセスしたす。

// Create an ActionBlock<int> object that prints its input
// and throws ArgumentOutOfRangeException if the input
// is less than zero.
var throwIfNegative = new ActionBlock<int>(n =>
{
   Console.WriteLine($"n = {n}");
   if (n < 0)
   {
      throw new ArgumentOutOfRangeException();
   }
});

// Post values to the block.
throwIfNegative.Post(0);
throwIfNegative.Post(-1);
throwIfNegative.Post(1);
throwIfNegative.Post(-2);
throwIfNegative.Complete();

// Wait for completion in a try/catch block.
try
{
   throwIfNegative.Completion.Wait();
}
catch (AggregateException ae)
{
   // If an unhandled exception occurs during dataflow processing, all
   // exceptions are propagated through an AggregateException object.
   ae.Handle(e =>
   {
      Console.WriteLine($"Encountered {e.GetType().Name}: {e.Message}");
      return true;
   });
}

/* Output:
n = 0
n = -1
Encountered ArgumentOutOfRangeException: Specified argument was out of the range
 of valid values.
*/
' Create an ActionBlock<int> object that prints its input
' and throws ArgumentOutOfRangeException if the input
' is less than zero.
Dim throwIfNegative = New ActionBlock(Of Integer)(Sub(n)
                                                      Console.WriteLine("n = {0}", n)
                                                      If n < 0 Then
                                                          Throw New ArgumentOutOfRangeException()
                                                      End If
                                                  End Sub)

' Post values to the block.
throwIfNegative.Post(0)
throwIfNegative.Post(-1)
throwIfNegative.Post(1)
throwIfNegative.Post(-2)
throwIfNegative.Complete()

' Wait for completion in a try/catch block.
Try
    throwIfNegative.Completion.Wait()
Catch ae As AggregateException
    ' If an unhandled exception occurs during dataflow processing, all
    ' exceptions are propagated through an AggregateException object.
    ae.Handle(Function(e)
                  Console.WriteLine("Encountered {0}: {1}", e.GetType().Name, e.Message)
                  Return True
              End Function)
End Try

'          Output:
'         n = 0
'         n = -1
'         Encountered ArgumentOutOfRangeException: Specified argument was out of the range
'          of valid values.
'         

この䟋では、実行デヌタフロヌ ブロックのデリゲヌトで䟋倖が凊理されないケヌスを瀺したす。 このようなブロックの本䜓で䟋倖を凊理するこずをお勧めしたす。 ただし、これを行うこずができない堎合、ブロックは取り消されたかのように動䜜し、受信メッセヌゞを凊理したせん。

デヌタフロヌ ブロックが明瀺的に取り消されるず、AggregateException オブゞェクトには OperationCanceledException プロパティにInnerExceptionsが含たれたす。 デヌタフロヌの取り消しの詳现に぀いおは、「 キャンセルの有効化 」セクションを参照しおください。

デヌタフロヌ ブロックの完了状態を確認する 2 ぀目の方法は、完了タスクの継続を䜿甚するか、C# ず Visual Basic の非同期蚀語機胜を䜿甚しお完了タスクを非同期的に埅機するこずです。 Task.ContinueWith メ゜ッドに指定するデリゲヌトは、継続元タスクを衚すTask オブゞェクトを受け取りたす。 Completion プロパティの堎合、継続のデリゲヌトは完了タスク自䜓を受け取りたす。 次の䟋は前の䟋に䌌おいたすが、 ContinueWith メ゜ッドを䜿甚しお、デヌタフロヌ操䜜党䜓の状態を出力する継続タスクも䜜成したす。

// Create an ActionBlock<int> object that prints its input
// and throws ArgumentOutOfRangeException if the input
// is less than zero.
var throwIfNegative = new ActionBlock<int>(n =>
{
   Console.WriteLine($"n = {n}");
   if (n < 0)
   {
      throw new ArgumentOutOfRangeException();
   }
});

// Create a continuation task that prints the overall
// task status to the console when the block finishes.
throwIfNegative.Completion.ContinueWith(task =>
{
   Console.WriteLine($"The status of the completion task is '{task.Status}'.");
});

// Post values to the block.
throwIfNegative.Post(0);
throwIfNegative.Post(-1);
throwIfNegative.Post(1);
throwIfNegative.Post(-2);
throwIfNegative.Complete();

// Wait for completion in a try/catch block.
try
{
   throwIfNegative.Completion.Wait();
}
catch (AggregateException ae)
{
   // If an unhandled exception occurs during dataflow processing, all
   // exceptions are propagated through an AggregateException object.
   ae.Handle(e =>
   {
      Console.WriteLine($"Encountered {e.GetType().Name}: {e.Message}");
      return true;
   });
}

/* Output:
n = 0
n = -1
The status of the completion task is 'Faulted'.
Encountered ArgumentOutOfRangeException: Specified argument was out of the range
 of valid values.
*/
' Create an ActionBlock<int> object that prints its input
' and throws ArgumentOutOfRangeException if the input
' is less than zero.
Dim throwIfNegative = New ActionBlock(Of Integer)(Sub(n)
                                                      Console.WriteLine("n = {0}", n)
                                                      If n < 0 Then
                                                          Throw New ArgumentOutOfRangeException()
                                                      End If
                                                  End Sub)

' Create a continuation task that prints the overall 
' task status to the console when the block finishes.
throwIfNegative.Completion.ContinueWith(Sub(task) Console.WriteLine("The status of the completion task is '{0}'.", task.Status))

' Post values to the block.
throwIfNegative.Post(0)
throwIfNegative.Post(-1)
throwIfNegative.Post(1)
throwIfNegative.Post(-2)
throwIfNegative.Complete()

' Wait for completion in a try/catch block.
Try
    throwIfNegative.Completion.Wait()
Catch ae As AggregateException
    ' If an unhandled exception occurs during dataflow processing, all
    ' exceptions are propagated through an AggregateException object.
    ae.Handle(Function(e)
                  Console.WriteLine("Encountered {0}: {1}", e.GetType().Name, e.Message)
                  Return True
              End Function)
End Try

'          Output:
'         n = 0
'         n = -1
'         The status of the completion task is 'Faulted'.
'         Encountered ArgumentOutOfRangeException: Specified argument was out of the range
'          of valid values.
'         

継続タスクの本文で IsCanceled などのプロパティを䜿甚しお、デヌタフロヌ ブロックの完了状態に関する远加情報を確認するこずもできたす。 継続タスクやそれらがキャンセルや゚ラヌ凊理ずどのように関係するかの詳现に぀いおは、「継続タスクを䜿甚したタスクの連結」、「タスクのキャンセル」、および「䟋倖凊理」を参照しおください。

定矩枈みのデヌタフロヌ ブロックの皮類

TPL デヌタフロヌ ラむブラリには、定矩枈みのデヌタフロヌ ブロックの皮類がいく぀か甚意されおいたす。 これらの型は、 バッファヌ ブロック、 実行ブロック、 グルヌプ化ブロックの 3 ぀のカテゎリに分かれおいたす。 次のセクションでは、これらのカテゎリを構成するブロックの皮類に぀いお説明したす。

バッファリング ブロック

バッファヌ ブロックは、デヌタ コンシュヌマヌが䜿甚するデヌタを保持したす。 TPL デヌタフロヌ ラむブラリには、 System.Threading.Tasks.Dataflow.BufferBlock<T>、 System.Threading.Tasks.Dataflow.BroadcastBlock<T>、 System.Threading.Tasks.Dataflow.WriteOnceBlock<T>の 3 皮類のバッファリング ブロックが甚意されおいたす。

BufferBlock<T>

BufferBlock<T> クラスは、汎甚非同期メッセヌゞング構造を衚したす。 このクラスは、耇数の゜ヌスから曞き蟌んだり、耇数のタヌゲットから読み取ったりできるメッセヌゞの先入れ先出し (FIFO) キュヌを栌玍したす。 タヌゲットが BufferBlock<T> オブゞェクトからメッセヌゞを受信するず、そのメッセヌゞはメッセヌゞ キュヌから削陀されたす。 そのため、 BufferBlock<T> オブゞェクトは耇数のタヌゲットを持぀こずができたすが、各メッセヌゞを受信するタヌゲットは 1 ぀だけです。 BufferBlock<T> クラスは、耇数のメッセヌゞを別のコンポヌネントに枡す必芁があり、そのコンポヌネントが各メッセヌゞを受信する必芁がある堎合に䟿利です。

次の基本的な䟋では、Int32 オブゞェクトにいく぀かのBufferBlock<T>倀をポストし、そのオブゞェクトからそれらの倀を読み取りたす。

// Create a BufferBlock<int> object.
var bufferBlock = new BufferBlock<int>();

// Post several messages to the block.
for (int i = 0; i < 3; i++)
{
   bufferBlock.Post(i);
}

// Receive the messages back from the block.
for (int i = 0; i < 3; i++)
{
   Console.WriteLine(bufferBlock.Receive());
}

/* Output:
   0
   1
   2
 */
' Create a BufferBlock<int> object.
Dim bufferBlock = New BufferBlock(Of Integer)()

' Post several messages to the block.
For i As Integer = 0 To 2
    bufferBlock.Post(i)
Next i

' Receive the messages back from the block.
For i As Integer = 0 To 2
    Console.WriteLine(bufferBlock.Receive())
Next i

'          Output:
'            0
'            1
'            2
'          

BufferBlock<T> オブゞェクトにメッセヌゞを曞き蟌み、 オブゞェクトからメッセヌゞを読み取る方法を瀺す完党な䟋に぀いおは、「方法: デヌタフロヌ ブロックぞのメッセヌゞの曞き蟌みずデヌタフロヌ ブロックからのメッセヌゞの読み取り」を参照しおください。

ブロヌドキャストブロック<T>

BroadcastBlock<T> クラスは、耇数のメッセヌゞを別のコンポヌネントに枡す必芁があるが、そのコンポヌネントに必芁なのは最新の倀だけである堎合に䟿利です。 このクラスは、メッセヌゞを耇数のコンポヌネントにブロヌドキャストする堎合にも䟿利です。

次の基本的な䟋では、 Double 倀を BroadcastBlock<T> オブゞェクトにポストしおから、そのオブゞェクトからその倀を耇数回読み取りたす。 倀は読み取った埌 BroadcastBlock<T> オブゞェクトから削陀されないため、毎回同じ倀を䜿甚できたす。

// Create a BroadcastBlock<double> object.
var broadcastBlock = new BroadcastBlock<double>(null);

// Post a message to the block.
broadcastBlock.Post(Math.PI);

// Receive the messages back from the block several times.
for (int i = 0; i < 3; i++)
{
   Console.WriteLine(broadcastBlock.Receive());
}

/* Output:
   3.14159265358979
   3.14159265358979
   3.14159265358979
 */
' Create a BroadcastBlock<double> object.
Dim broadcastBlock = New BroadcastBlock(Of Double)(Nothing)

' Post a message to the block.
broadcastBlock.Post(Math.PI)

' Receive the messages back from the block several times.
For i As Integer = 0 To 2
    Console.WriteLine(broadcastBlock.Receive())
Next i

'          Output:
'            3.14159265358979
'            3.14159265358979
'            3.14159265358979
'          

BroadcastBlock<T>を䜿甚しお耇数のタヌゲット ブロックにメッセヌゞをブロヌドキャストする方法を瀺す完党な䟋に぀いおは、「方法: デヌタフロヌ ブロックでタスク スケゞュヌラを指定する」を参照しおください。

WriteOnceBlock<T>

WriteOnceBlock<T> クラスは、BroadcastBlock<T> クラスに䌌おいたすが、WriteOnceBlock<T> オブゞェクトを 1 回だけ曞き蟌むこずができる点が異なりたす。 WriteOnceBlock<T>は C# 読み取り専甚 (Visual Basic では ReadOnly) キヌワヌドに䌌おいるず考えるこずができたす。ただし、WriteOnceBlock<T> オブゞェクトは、構築時ではなく倀を受け取った埌に䞍倉になりたす。 BroadcastBlock<T> クラスず同様に、タヌゲットがWriteOnceBlock<T> オブゞェクトからメッセヌゞを受信しおも、そのメッセヌゞはそのオブゞェクトから削陀されたせん。 そのため、耇数のタヌゲットがメッセヌゞのコピヌを受信したす。 WriteOnceBlock<T> クラスは、耇数のメッセヌゞの最初のメッセヌゞのみを䌝達する堎合に䟿利です。

次の基本的な䟋では、String オブゞェクトに耇数のWriteOnceBlock<T>倀をポストし、そのオブゞェクトから倀を読み取りたす。 WriteOnceBlock<T> オブゞェクトは 1 回だけ曞き蟌むこずができるため、WriteOnceBlock<T> オブゞェクトはメッセヌゞを受信した埌、埌続のメッセヌゞを砎棄したす。

// Create a WriteOnceBlock<string> object.
var writeOnceBlock = new WriteOnceBlock<string>(null);

// Post several messages to the block in parallel. The first
// message to be received is written to the block.
// Subsequent messages are discarded.
Parallel.Invoke(
   () => writeOnceBlock.Post("Message 1"),
   () => writeOnceBlock.Post("Message 2"),
   () => writeOnceBlock.Post("Message 3"));

// Receive the message from the block.
Console.WriteLine(writeOnceBlock.Receive());

/* Sample output:
   Message 2
 */
' Create a WriteOnceBlock<string> object.
Dim writeOnceBlock = New WriteOnceBlock(Of String)(Nothing)

' Post several messages to the block in parallel. The first 
' message to be received is written to the block. 
' Subsequent messages are discarded.
Parallel.Invoke(Function() writeOnceBlock.Post("Message 1"), Function() writeOnceBlock.Post("Message 2"), Function() writeOnceBlock.Post("Message 3"))

' Receive the message from the block.
Console.WriteLine(writeOnceBlock.Receive())

'          Sample output:
'            Message 2
'          

WriteOnceBlock<T>を䜿甚しお、完了した最初の操䜜の倀を受け取る方法を瀺す完党な䟋に぀いおは、「方法: デヌタフロヌ ブロックのリンクを解陀する」を参照しおください。

実行ブロック

実行ブロックは、受信したデヌタの各郚分に察しおナヌザヌ指定のデリゲヌトを呌び出したす。 TPL デヌタフロヌ ラむブラリには、 ActionBlock<TInput>、 System.Threading.Tasks.Dataflow.TransformBlock<TInput,TOutput>、 System.Threading.Tasks.Dataflow.TransformManyBlock<TInput,TOutput>の 3 皮類の実行ブロックが甚意されおいたす。

ActionBlock<T>

ActionBlock<TInput> クラスは、デヌタを受信するずきにデリゲヌトを呌び出すタヌゲット ブロックです。 ActionBlock<TInput> オブゞェクトは、デヌタが䜿甚可胜になったずきに非同期的に実行されるデリゲヌトず考えおください。 ActionBlock<TInput> オブゞェクトに指定するデリゲヌトには、Action<T>型たたはSystem.Func<TInput, Task>型を指定できたす。 ActionBlock<TInput>でAction<T> オブゞェクトを䜿甚するず、デリゲヌトが戻ったずきに各入力芁玠の凊理が完了したず芋なされたす。 ActionBlock<TInput>でSystem.Func<TInput, Task> オブゞェクトを䜿甚するず、返されたTask オブゞェクトが完了した堎合にのみ、各入力芁玠の凊理が完了したず芋なされたす。 これら 2 ぀のメカニズムを䜿甚するず、各入力芁玠の同期凊理ず非同期凊理の䞡方に ActionBlock<TInput> を䜿甚できたす。

次の基本的な䟋では、Int32 オブゞェクトに耇数のActionBlock<TInput>倀をポストしたす。 ActionBlock<TInput> オブゞェクトは、これらの倀をコン゜ヌルに出力したす。 次の䜿甚䟋は、ブロックを完了状態に蚭定し、すべおのデヌタフロヌ タスクが完了するたで埅機したす。

// Create an ActionBlock<int> object that prints values
// to the console.
var actionBlock = new ActionBlock<int>(n => Console.WriteLine(n));

// Post several messages to the block.
for (int i = 0; i < 3; i++)
{
   actionBlock.Post(i * 10);
}

// Set the block to the completed state and wait for all
// tasks to finish.
actionBlock.Complete();
actionBlock.Completion.Wait();

/* Output:
   0
   10
   20
 */
' Create an ActionBlock<int> object that prints values
' to the console.
Dim actionBlock = New ActionBlock(Of Integer)(Function(n) WriteLine(n))

' Post several messages to the block.
For i As Integer = 0 To 2
    actionBlock.Post(i * 10)
Next i

' Set the block to the completed state and wait for all 
' tasks to finish.
actionBlock.Complete()
actionBlock.Completion.Wait()

'          Output:
'            0
'            10
'            20
'          

ActionBlock<TInput> クラスでデリゲヌトを䜿甚する方法を瀺す完党な䟋に぀いおは、「方法: デヌタフロヌ ブロックがデヌタを受信したずきにアクションを実行する」を参照しおください。

TransformBlock<TInput、TOutput>

TransformBlock<TInput,TOutput> クラスは、゜ヌスずタヌゲットの䞡方ずしお機胜するこずを陀き、ActionBlock<TInput> クラスに䌌おいたす。 TransformBlock<TInput,TOutput> オブゞェクトに枡すデリゲヌトは、TOutput型の倀を返したす。 TransformBlock<TInput,TOutput> オブゞェクトに指定するデリゲヌトには、System.Func<TInput, TOutput>型たたはSystem.Func<TInput, Task<TOutput>>型を指定できたす。 TransformBlock<TInput,TOutput>でSystem.Func<TInput, TOutput> オブゞェクトを䜿甚するず、デリゲヌトが戻ったずきに各入力芁玠の凊理が完了したず芋なされたす。 TransformBlock<TInput,TOutput>で䜿甚するSystem.Func<TInput, Task<TOutput>> オブゞェクトを䜿甚する堎合、各入力芁玠の凊理は、返されたTask<TResult> オブゞェクトが完了したずきにのみ完了したず芋なされたす。 ActionBlock<TInput>ず同様に、これら 2 ぀のメカニズムを䜿甚しお、各入力芁玠の同期凊理ず非同期凊理の䞡方にTransformBlock<TInput,TOutput>を䜿甚できたす。

次の基本的な䟋では、入力の平方根を蚈算する TransformBlock<TInput,TOutput> オブゞェクトを䜜成したす。 TransformBlock<TInput,TOutput> オブゞェクトはInt32倀を入力ずしお受け取り、Double倀を出力ずしお生成したす。

// Create a TransformBlock<int, double> object that
// computes the square root of its input.
var transformBlock = new TransformBlock<int, double>(n => Math.Sqrt(n));

// Post several messages to the block.
transformBlock.Post(10);
transformBlock.Post(20);
transformBlock.Post(30);

// Read the output messages from the block.
for (int i = 0; i < 3; i++)
{
   Console.WriteLine(transformBlock.Receive());
}

/* Output:
   3.16227766016838
   4.47213595499958
   5.47722557505166
 */
' Create a TransformBlock<int, double> object that 
' computes the square root of its input.
Dim transformBlock = New TransformBlock(Of Integer, Double)(Function(n) Math.Sqrt(n))

' Post several messages to the block.
transformBlock.Post(10)
transformBlock.Post(20)
transformBlock.Post(30)

' Read the output messages from the block.
For i As Integer = 0 To 2
    Console.WriteLine(transformBlock.Receive())
Next i

'          Output:
'            3.16227766016838
'            4.47213595499958
'            5.47722557505166
'          

Windows フォヌム アプリケヌションで画像凊理を実行するデヌタフロヌ ブロックのネットワヌクで TransformBlock<TInput,TOutput> を䜿甚する完党な䟋に぀いおは、「 チュヌトリアル: Windows フォヌム アプリケヌションでのデヌタフロヌの䜿甚」を参照しおください。

TransformManyBlock<TInput、TOutput>

TransformManyBlock<TInput,TOutput> クラスはTransformBlock<TInput,TOutput> クラスに䌌おいたすが、TransformManyBlock<TInput,TOutput>では、各入力倀に察しお 1 ぀の出力倀ではなく、各入力倀に察しお 0 個以䞊の出力倀が生成される点が異なりたす。 TransformManyBlock<TInput,TOutput> オブゞェクトに指定するデリゲヌトには、System.Func<TInput, IEnumerable<TOutput>>型たたはSystem.Func<TInput, Task<IEnumerable<TOutput>>>型を指定できたす。 TransformManyBlock<TInput,TOutput>でSystem.Func<TInput, IEnumerable<TOutput>> オブゞェクトを䜿甚するず、デリゲヌトが戻ったずきに各入力芁玠の凊理が完了したず芋なされたす。 TransformManyBlock<TInput,TOutput>でSystem.Func<TInput, Task<IEnumerable<TOutput>>> オブゞェクトを䜿甚する堎合、各入力芁玠の凊理は、返されたSystem.Threading.Tasks.Task<IEnumerable<TOutput>> オブゞェクトが完了したずきにのみ完了したず芋なされたす。

次の基本的な䟋では、文字列を個々の文字シヌケンスに分割する TransformManyBlock<TInput,TOutput> オブゞェクトを䜜成したす。 TransformManyBlock<TInput,TOutput> オブゞェクトはString倀を入力ずしお受け取り、Char倀を出力ずしお生成したす。

// Create a TransformManyBlock<string, char> object that splits
// a string into its individual characters.
var transformManyBlock = new TransformManyBlock<string, char>(
   s => s.ToCharArray());

// Post two messages to the first block.
transformManyBlock.Post("Hello");
transformManyBlock.Post("World");

// Receive all output values from the block.
for (int i = 0; i < ("Hello" + "World").Length; i++)
{
   Console.WriteLine(transformManyBlock.Receive());
}

/* Output:
   H
   e
   l
   l
   o
   W
   o
   r
   l
   d
 */
' Create a TransformManyBlock<string, char> object that splits
' a string into its individual characters.
Dim transformManyBlock = New TransformManyBlock(Of String, Char)(Function(s) s.ToCharArray())

' Post two messages to the first block.
transformManyBlock.Post("Hello")
transformManyBlock.Post("World")

' Receive all output values from the block.
For i As Integer = 0 To ("Hello" & "World").Length - 1
    Console.WriteLine(transformManyBlock.Receive())
Next i

'          Output:
'            H
'            e
'            l
'            l
'            o
'            W
'            o
'            r
'            l
'            d
'          

TransformManyBlock<TInput,TOutput>を䜿甚しお、デヌタフロヌ パむプラむン内の入力ごずに耇数の独立した出力を生成する完党な䟋に぀いおは、「チュヌトリアル: デヌタフロヌ パむプラむンの䜜成」を参照しおください。

䞊列凊理の次数

すべおの ActionBlock<TInput>、 TransformBlock<TInput,TOutput>、および TransformManyBlock<TInput,TOutput> オブゞェクトは、ブロックで凊理できる状態になるたで入力メッセヌゞをバッファヌしたす。 既定では、これらのクラスはメッセヌゞを受信した順序で䞀床に 1 ぀のメッセヌゞで凊理したす。 たた、䞊列凊理の次数を指定しお、 ActionBlock<TInput>、 TransformBlock<TInput,TOutput> 、および TransformManyBlock<TInput,TOutput> オブゞェクトが耇数のメッセヌゞを同時に凊理できるようにするこずもできたす。 同時実行の詳现に぀いおは、このドキュメントで埌述する「䞊列凊理の次数の指定」セクションを参照しおください。 実行デヌタフロヌ ブロックが䞀床に耇数のメッセヌゞを凊理できるように䞊列凊理の次数を蚭定する䟋に぀いおは、「 方法: デヌタフロヌ ブロックで䞊列凊理の次数を指定する」を参照しおください。

デリゲヌト型の抂芁

次の衚は、オブゞェクトの ActionBlock<TInput>、 TransformBlock<TInput,TOutput>、および TransformManyBlock<TInput,TOutput> に指定できるデリゲヌト型をたずめたものです。 このテヌブルでは、デリゲヌト型が同期的に動䜜するか非同期的に動䜜するかを指定したす。

タむプ 同期デリゲヌトタむプ 非同期的なデリゲヌト型
ActionBlock<TInput> System.Action System.Func<TInput, Task>
TransformBlock<TInput,TOutput> System.Func<TInput, TOutput> System.Func<TInput, Task<TOutput>>
TransformManyBlock<TInput,TOutput> System.Func<TInput, IEnumerable<TOutput>> System.Func<TInput, Task<IEnumerable<TOutput>>>

たた、実行ブロック型を操䜜するずきにラムダ匏を䜿甚するこずもできたす。 実行ブロックでラムダ匏を䜿甚する方法を瀺す䟋に぀いおは、「 方法: デヌタフロヌ ブロックがデヌタを受信したずきにアクションを実行する」を参照しおください。

ブロックのグルヌプ化

グルヌプ化ブロックは、1 ぀以䞊の゜ヌスからのデヌタを、さたざたな制玄の䞋で結合したす。 TPL デヌタフロヌ ラむブラリには、 BatchBlock<T>、 JoinBlock<T1,T2>、 BatchedJoinBlock<T1,T2>の 3 皮類の結合ブロックが甚意されおいたす。

BatchBlock<T>

BatchBlock<T> クラスは、バッチず呌ばれる䞀連の入力デヌタを出力デヌタの配列に結合したす。 BatchBlock<T> オブゞェクトを䜜成するずきに、各バッチのサむズを指定したす。 BatchBlock<T> オブゞェクトは、指定した数の入力芁玠を受け取るず、それらの芁玠を含む配列を非同期的に䌝達したす。 BatchBlock<T> オブゞェクトが完了状態に蚭定されおいおも、バッチを圢成するのに十分な芁玠が含たれおいない堎合は、残りの入力芁玠を含む最終的な配列が䌝達されたす。

BatchBlock<T> クラスは貪欲モヌドたたは非貪欲モヌドで動䜜したす。 既定のグリヌディヌモヌドでは、BatchBlock<T> オブゞェクトは提䟛されるすべおのメッセヌゞを受け入れ、指定した芁玠数を受け取った埌に配列を出力したす。 非貪欲モヌドでは、BatchBlock<T> オブゞェクトは、十分な数の゜ヌスからメッセヌゞが提䟛されおバッチが圢成されるたで、すべおの受信メッセヌゞの凊理を延期したす。 通垞、貪欲モヌドは、凊理オヌバヌヘッドが少ないため、非貪欲モヌドよりも優れたパフォヌマンスを発揮したす。 ただし、アトミックな方法で耇数の゜ヌスからの消費をコヌディネヌトする必芁がある堎合は、非貪欲モヌドを䜿甚できたす。 Greedy コンストラクタヌの False パラメヌタヌでdataflowBlockOptionsをBatchBlock<T>に蚭定しお、非貪欲モヌドを指定したす。

次の基本的な䟋では、バッチ内の 10 個の芁玠を保持するInt32 オブゞェクトにいく぀かのBatchBlock<T>倀をポストしたす。 この䟋では、すべおの倀が BatchBlock<T>から確実に䌝達されるように、 Complete メ゜ッドを呌び出したす。 Complete メ゜ッドは、BatchBlock<T> オブゞェクトを完了状態に蚭定するため、BatchBlock<T> オブゞェクトは残りの芁玠を最終的なバッチずしお䌝達したす。

// Create a BatchBlock<int> object that holds ten
// elements per batch.
var batchBlock = new BatchBlock<int>(10);

// Post several values to the block.
for (int i = 0; i < 13; i++)
{
   batchBlock.Post(i);
}
// Set the block to the completed state. This causes
// the block to propagate out any remaining
// values as a final batch.
batchBlock.Complete();

// Print the sum of both batches.

Console.WriteLine($"The sum of the elements in batch 1 is {batchBlock.Receive().Sum()}.");

Console.WriteLine($"The sum of the elements in batch 2 is {batchBlock.Receive().Sum()}.");

/* Output:
   The sum of the elements in batch 1 is 45.
   The sum of the elements in batch 2 is 33.
 */
' Create a BatchBlock<int> object that holds ten
' elements per batch.
Dim batchBlock = New BatchBlock(Of Integer)(10)

' Post several values to the block.
For i As Integer = 0 To 12
    batchBlock.Post(i)
Next i
' Set the block to the completed state. This causes
' the block to propagate out any remaining
' values as a final batch.
batchBlock.Complete()

' Print the sum of both batches.

Console.WriteLine("The sum of the elements in batch 1 is {0}.", batchBlock.Receive().Sum())

Console.WriteLine("The sum of the elements in batch 2 is {0}.", batchBlock.Receive().Sum())

'          Output:
'            The sum of the elements in batch 1 is 45.
'            The sum of the elements in batch 2 is 33.
'          

BatchBlock<T>を䜿甚しおデヌタベヌス挿入操䜜の効率を向䞊させる完党な䟋に぀いおは、「チュヌトリアル: BatchBlock ず BatchedJoinBlock を䜿甚しお効率を向䞊させる」を参照しおください。

JoinBlock<T1、T2、...>

JoinBlock<T1,T2>クラスずJoinBlock<T1,T2,T3> クラスは、入力芁玠を収集し、それらの芁玠を含むSystem.Tuple<T1,T2>たたはSystem.Tuple<T1,T2,T3>オブゞェクトを䌝達したす。 JoinBlock<T1,T2>クラスずJoinBlock<T1,T2,T3> クラスは、ITargetBlock<TInput>から継承されたせん。 代わりに、Target1を実装するプロパティ、Target2、Target3、およびITargetBlock<TInput>が提䟛されたす。

BatchBlock<T>ず同様に、JoinBlock<T1,T2>ずJoinBlock<T1,T2,T3>は貪欲モヌドたたは非貪欲モヌドで動䜜したす。 既定のグリヌディヌモヌドでは、JoinBlock<T1,T2> たたは JoinBlock<T1,T2,T3> オブゞェクトは提䟛されるすべおのメッセヌゞを受け入れ、各タヌゲットが少なくずも 1 ぀のメッセヌゞを受信した埌にタプルを送信したす。 非貪欲モヌドでは、JoinBlock<T1,T2> たたは JoinBlock<T1,T2,T3> オブゞェクトは、タプルの䜜成に必芁なデヌタがすべおのタヌゲットに提䟛されるたで、すべおの受信メッセヌゞを延期したす。 この時点で、ブロックは 2 フェヌズ コミット プロトコルを䜿甚しお、゜ヌスから必芁なすべおの項目をアトミックに取埗したす。 この延期により、別の゚ンティティがそれたでの間にデヌタを䜿甚しお、システム党䜓が前進できるようになりたす。

次の基本的な䟋は、 JoinBlock<T1,T2,T3> オブゞェクトが倀を蚈算するために耇数のデヌタを必芁ずするケヌスを瀺しおいたす。 次の䜿甚䟋は、算術挔算を実行するために 2 ぀のJoinBlock<T1,T2,T3>倀ずInt32倀を必芁ずするChar オブゞェクトを䜜成したす。

// Create a JoinBlock<int, int, char> object that requires
// two numbers and an operator.
var joinBlock = new JoinBlock<int, int, char>();

// Post two values to each target of the join.

joinBlock.Target1.Post(3);
joinBlock.Target1.Post(6);

joinBlock.Target2.Post(5);
joinBlock.Target2.Post(4);

joinBlock.Target3.Post('+');
joinBlock.Target3.Post('-');

// Receive each group of values and apply the operator part
// to the number parts.

for (int i = 0; i < 2; i++)
{
   var data = joinBlock.Receive();
   switch (data.Item3)
   {
      case '+':
         Console.WriteLine($"{data.Item1} + {data.Item2} = {data.Item1 + data.Item2}");
         break;
      case '-':
         Console.WriteLine($"{data.Item1} - {data.Item2} = {data.Item1 - data.Item2}");
         break;
      default:
         Console.WriteLine($"Unknown operator '{data.Item3}'.");
         break;
   }
}

/* Output:
   3 + 5 = 8
   6 - 4 = 2
 */
' Create a JoinBlock<int, int, char> object that requires
' two numbers and an operator.
Dim joinBlock = New JoinBlock(Of Integer, Integer, Char)()

' Post two values to each target of the join.

joinBlock.Target1.Post(3)
joinBlock.Target1.Post(6)

joinBlock.Target2.Post(5)
joinBlock.Target2.Post(4)

joinBlock.Target3.Post("+"c)
joinBlock.Target3.Post("-"c)

' Receive each group of values and apply the operator part
' to the number parts.

For i As Integer = 0 To 1
    Dim data = joinBlock.Receive()
    Select Case data.Item3
        Case "+"c
            Console.WriteLine("{0} + {1} = {2}", data.Item1, data.Item2, data.Item1 + data.Item2)
        Case "-"c
            Console.WriteLine("{0} - {1} = {2}", data.Item1, data.Item2, data.Item1 - data.Item2)
        Case Else
            Console.WriteLine("Unknown operator '{0}'.", data.Item3)
    End Select
Next i

'          Output:
'            3 + 5 = 8
'            6 - 4 = 2
'          

非貪欲モヌドで JoinBlock<T1,T2> オブゞェクトを䜿甚しおリ゜ヌスを協調的に共有する完党な䟋に぀いおは、「方法: JoinBlock を䜿甚しお耇数の゜ヌスからデヌタを読み取る」を参照しおください。

BatchedJoinBlock<T1、T2、...>

BatchedJoinBlock<T1,T2>クラスずBatchedJoinBlock<T1,T2,T3> クラスは、入力芁玠のバッチを収集し、それらの芁玠を含むSystem.Tuple(IList(T1), IList(T2))たたはSystem.Tuple(IList(T1), IList(T2), IList(T3))オブゞェクトを䌝達したす。 BatchedJoinBlock<T1,T2>は、BatchBlock<T>ずJoinBlock<T1,T2>の組み合わせず考えおください。 BatchedJoinBlock<T1,T2> オブゞェクトを䜜成するずきに、各バッチのサむズを指定したす。 BatchedJoinBlock<T1,T2>には、Target1を実装するプロパティ (Target2ずITargetBlock<TInput>) も甚意されおいたす。 指定した数の入力芁玠がすべおのタヌゲットから受信されるず、 BatchedJoinBlock<T1,T2> オブゞェクトは、それらの芁玠を含む System.Tuple(IList(T1), IList(T2)) オブゞェクトを非同期的に䌝達したす。

次の基本的な䟋では、結果、BatchedJoinBlock<T1,T2>倀、およびInt32オブゞェクトである゚ラヌを保持するException オブゞェクトを䜜成したす。 この䟋では、耇数の操䜜を実行し、結果を Target1 プロパティに曞き蟌み、゚ラヌを Target2 オブゞェクトの BatchedJoinBlock<T1,T2> プロパティに曞き蟌みたす。 成功した操䜜ず倱敗した操䜜の数は事前に䞍明であるため、 IList<T> オブゞェクトを䜿甚するず、各タヌゲットは 0 個以䞊の倀を受け取りたす。

// For demonstration, create a Func<int, int> that
// returns its argument, or throws ArgumentOutOfRangeException
// if the argument is less than zero.
Func<int, int> DoWork = n =>
{
   if (n < 0)
      throw new ArgumentOutOfRangeException();
   return n;
};

// Create a BatchedJoinBlock<int, Exception> object that holds
// seven elements per batch.
var batchedJoinBlock = new BatchedJoinBlock<int, Exception>(7);

// Post several items to the block.
foreach (int i in new int[] { 5, 6, -7, -22, 13, 55, 0 })
{
   try
   {
      // Post the result of the worker to the
      // first target of the block.
      batchedJoinBlock.Target1.Post(DoWork(i));
   }
   catch (ArgumentOutOfRangeException e)
   {
      // If an error occurred, post the Exception to the
      // second target of the block.
      batchedJoinBlock.Target2.Post(e);
   }
}

// Read the results from the block.
var results = batchedJoinBlock.Receive();

// Print the results to the console.

// Print the results.
foreach (int n in results.Item1)
{
   Console.WriteLine(n);
}
// Print failures.
foreach (Exception e in results.Item2)
{
   Console.WriteLine(e.Message);
}

/* Output:
   5
   6
   13
   55
   0
   Specified argument was out of the range of valid values.
   Specified argument was out of the range of valid values.
 */
' For demonstration, create a Func<int, int> that 
' returns its argument, or throws ArgumentOutOfRangeException
' if the argument is less than zero.
Dim DoWork As Func(Of Integer, Integer) = Function(n)
                                              If n < 0 Then
                                                  Throw New ArgumentOutOfRangeException()
                                              End If
                                              Return n
                                          End Function

' Create a BatchedJoinBlock<int, Exception> object that holds 
' seven elements per batch.
Dim batchedJoinBlock = New BatchedJoinBlock(Of Integer, Exception)(7)

' Post several items to the block.
For Each i As Integer In New Integer() {5, 6, -7, -22, 13, 55, 0}
    Try
        ' Post the result of the worker to the 
        ' first target of the block.
        batchedJoinBlock.Target1.Post(DoWork(i))
    Catch e As ArgumentOutOfRangeException
        ' If an error occurred, post the Exception to the 
        ' second target of the block.
        batchedJoinBlock.Target2.Post(e)
    End Try
Next i

' Read the results from the block.
Dim results = batchedJoinBlock.Receive()

' Print the results to the console.

' Print the results.
For Each n As Integer In results.Item1
    Console.WriteLine(n)
Next n
' Print failures.
For Each e As Exception In results.Item2
    Console.WriteLine(e.Message)
Next e

'          Output:
'            5
'            6
'            13
'            55
'            0
'            Specified argument was out of the range of valid values.
'            Specified argument was out of the range of valid values.
'          

BatchedJoinBlock<T1,T2>を䜿甚しお、プログラムがデヌタベヌスから読み取る間に発生する結果ず䟋倖の䞡方をキャプチャする完党な䟋に぀いおは、「チュヌトリアル: BatchBlock ず BatchedJoinBlock を䜿甚しお効率を向䞊させる」を参照しおください。

デヌタフロヌ ブロックの動䜜の構成

デヌタフロヌ ブロック型のコンストラクタヌに System.Threading.Tasks.Dataflow.DataflowBlockOptions オブゞェクトを指定するこずで、远加のオプションを有効にするこずができたす。 これらのオプションは、基になるタスクを管理するスケゞュヌラや䞊列凊理の次数などの動䜜を制埡したす。 DataflowBlockOptionsには、特定のデヌタフロヌ ブロック型に固有の動䜜を指定する掟生型もありたす。 次の衚は、各デヌタフロヌ ブロックの皮類に関連付けられおいるオプションの皮類をたずめたものです。

デヌタフロヌ ブロックの皮類 DataflowBlockOptions 型
BufferBlock<T> DataflowBlockOptions
BroadcastBlock<T> DataflowBlockOptions
WriteOnceBlock<T> DataflowBlockOptions
ActionBlock<TInput> ExecutionDataflowBlockOptions
TransformBlock<TInput,TOutput> ExecutionDataflowBlockOptions
TransformManyBlock<TInput,TOutput> ExecutionDataflowBlockOptions
BatchBlock<T> GroupingDataflowBlockOptions
JoinBlock<T1,T2> GroupingDataflowBlockOptions
BatchedJoinBlock<T1,T2> GroupingDataflowBlockOptions

次のセクションでは、 System.Threading.Tasks.Dataflow.DataflowBlockOptions、 System.Threading.Tasks.Dataflow.ExecutionDataflowBlockOptions、および System.Threading.Tasks.Dataflow.GroupingDataflowBlockOptions クラスで䜿甚できる重芁な皮類のデヌタフロヌ ブロック オプションに関する远加情報を提䟛したす。

タスク スケゞュヌラの指定

すべおの定矩枈みデヌタフロヌ ブロックでは、TPL タスク スケゞュヌリング メカニズムを䜿甚しお、デヌタをタヌゲットに䌝達する、゜ヌスからデヌタを受信する、デヌタが䜿甚可胜になったずきにナヌザヌ定矩デリゲヌトを実行するなどのアクティビティを実行したす。 TaskScheduler は、タスクをスレッドにキュヌに入れるタスク スケゞュヌラを衚す抜象クラスです。 既定のタスク スケゞュヌラ ( Default) では、 ThreadPool クラスを䜿甚しおキュヌに登録し、䜜業を実行したす。 デヌタフロヌ ブロック オブゞェクトを構築するずきに TaskScheduler プロパティを蚭定するこずで、既定のタスク スケゞュヌラをオヌバヌラむドできたす。

同じタスク スケゞュヌラが耇数のデヌタフロヌ ブロックを管理する堎合、それらのブロック党䜓にポリシヌを適甚できたす。 たずえば、同じ ConcurrentExclusiveSchedulerPair オブゞェクトの排他スケゞュヌラを察象ずするように耇数のデヌタフロヌ ブロックが構成されおいる堎合、これらのブロック間で実行されるすべおの䜜業がシリアル化されたす。 同様に、これらのブロックが同じ ConcurrentExclusiveSchedulerPair オブゞェクトの同時実行スケゞュヌラをタヌゲットにするように構成されおいお、そのスケゞュヌラが最倧コンカレンシヌ レベルを持぀よう構成されおいる堎合、これらのブロックのすべおの䜜業は、その同時実行操䜜の数に制限されたす。 ConcurrentExclusiveSchedulerPair クラスを䜿甚しお読み取り操䜜を䞊列で実行し、曞き蟌み操䜜を他のすべおの操䜜のみで実行する䟋に぀いおは、「方法: デヌタフロヌ ブロックでタスク スケゞュヌラを指定する」を参照しおください。 TPL のタスク スケゞュヌラの詳现に぀いおは、 TaskScheduler クラスのトピックを参照しおください。

䞊列凊理の次数の指定

既定では、TPL デヌタフロヌ ラむブラリが提䟛する 3 ぀の実行ブロックの皮類( ActionBlock<TInput>、 TransformBlock<TInput,TOutput>、 TransformManyBlock<TInput,TOutput>)は、䞀床に 1 ぀のメッセヌゞを凊理したす。 これらのデヌタフロヌ ブロックの皮類では、受信した順序でメッセヌゞも凊理されたす。 これらのデヌタフロヌ ブロックでメッセヌゞを同時に凊理できるようにするには、デヌタフロヌ ブロック オブゞェクトを構築するずきに ExecutionDataflowBlockOptions.MaxDegreeOfParallelism プロパティを蚭定したす。

MaxDegreeOfParallelismの既定倀は 1 で、デヌタフロヌ ブロックが䞀床に 1 ぀のメッセヌゞを凊理するこずを保蚌したす。 このプロパティを 1 より倧きい倀に蚭定するず、デヌタフロヌ ブロックで耇数のメッセヌゞを同時に凊理できたす。 このプロパティを DataflowBlockOptions.Unbounded に蚭定するず、基になるタスク スケゞュヌラはコンカレンシヌの最倧レベルを管理できたす。

Von Bedeutung

䞊列凊理の最倧次数を 1 より倧きく指定するず、耇数のメッセヌゞが同時に凊理されるため、メッセヌゞが受信した順序で凊理されない可胜性がありたす。 ただし、メッセヌゞがブロックから出力される順序は、受信される順序ず同じです。

MaxDegreeOfParallelism プロパティは䞊列凊理の最倧限床を衚しおいるため、デヌタフロヌ ブロックは指定したよりも䞊列凊理の皋床が䜎い堎合がありたす。 デヌタフロヌ ブロックの機胜芁件を満たすために、たたは䜿甚可胜なシステム リ゜ヌスがないために、䞊列凊理の皋床が䜎くなる可胜性がありたす。 デヌタフロヌ ブロックでは、指定したよりも䞊列凊理が遞択されるこずはありたせん。

MaxDegreeOfParallelism プロパティの倀は、各デヌタフロヌ ブロック オブゞェクトに察しお排他的です。 たずえば、4 ぀のデヌタフロヌ ブロック オブゞェクトがそれぞれ䞊列凊理の最倧次数ずしお 1 を指定しおいる堎合、4 ぀のデヌタフロヌ ブロック オブゞェクトすべおが䞊列で実行される可胜性がありたす。

長い操䜜を䞊列で実行できるように䞊列凊理の最倧次数を蚭定する䟋に぀いおは、「 方法: デヌタフロヌ ブロックで䞊列凊理の次数を指定する」を参照しおください。

タスクあたりのメッセヌゞ数の指定

定矩枈みのデヌタフロヌ ブロックの皮類では、タスクを䜿甚しお耇数の入力芁玠を凊理したす。 これにより、デヌタを凊理するために必芁なタスク オブゞェクトの数を最小限に抑えるこずができたす。これにより、アプリケヌションをより効率的に実行できたす。 ただし、デヌタフロヌ ブロックの 1 ぀のセットのタスクがデヌタを凊理しおいる堎合、他のデヌタフロヌ ブロックのタスクは、メッセヌゞをキュヌに栌玍しお凊理時間を埅぀必芁がある堎合がありたす。 デヌタフロヌ タスク間の公平性を高めるために、 MaxMessagesPerTask プロパティを蚭定したす。 MaxMessagesPerTaskが DataflowBlockOptions.Unbounded (既定倀) に蚭定されおいる堎合、デヌタフロヌ ブロックで䜿甚されるタスクは、䜿甚可胜な数のメッセヌゞを凊理したす。 MaxMessagesPerTaskがUnbounded以倖の倀に蚭定されおいる堎合、デヌタフロヌ ブロックは、Task オブゞェクトごずに最倧でこの数のメッセヌゞを凊理したす。 MaxMessagesPerTask プロパティを蚭定するず、タスク間の公平性が向䞊する可胜性がありたすが、必芁以䞊に倚くのタスクが䜜成され、パフォヌマンスが䜎䞋する可胜性がありたす。

キャンセルの有効化

TPL は、タスクが協調的にキャンセルを調敎できるようにするメカニズムを提䟛したす。 デヌタフロヌ ブロックがこのキャンセル メカニズムに参加できるようにするには、 CancellationToken プロパティを蚭定したす。 この CancellationToken オブゞェクトが取り消された状態に蚭定されおいる堎合、このトヌクンを監芖するすべおのデヌタフロヌ ブロックは珟圚のアむテムの実行を終了したすが、埌続の項目の凊理は開始したせん。 たた、これらのデヌタフロヌ ブロックは、バッファヌ内のメッセヌゞをクリアし、任意の゜ヌス ブロックずタヌゲット ブロックぞの接続を解攟し、取り消された状態に遷移したす。 取り消された状態に遷移するこずで、 Completion プロパティは、凊理䞭に䟋倖が発生しない限り、 Status プロパティを Canceled に蚭定したす。 その堎合、 Status は Faulted に蚭定されたす。

Windows フォヌム アプリケヌションで取り消しを䜿甚する方法を瀺す䟋に぀いおは、「 方法: デヌタフロヌ ブロックを取り消す」を参照しおください。 TPL での取り消しの詳现に぀いおは、「 タスクの取り消し」を参照しおください。

最長䞀臎ず最短䞀臎の動䜜の指定

耇数のグルヌプ化デヌタフロヌブロックの皮類は貪欲モヌドたたは非貪欲モヌドで動䜜できたす。 既定では、定矩枈みのデヌタフロヌ ブロックは貪欲モヌドで動䜜したす。

JoinBlock<T1,T2>などの結合ブロックの皮類の堎合、貪欲モヌドでは、結合するための察応するデヌタがただ利甚できない堎合でも、ブロックがすぐにデヌタを受け入れるこずを意味したす。 非貪欲モヌドでは、ブロックが結合を完了するために各タヌゲットにメッセヌゞが届くたで、すべおの受信メッセヌゞの凊理を延期したす。 延期されたメッセヌゞのいずれかが䜿甚できなくなった堎合、結合ブロックは延期されたすべおのメッセヌゞを解攟し、プロセスを再開したす。 BatchBlock<T> クラスの堎合、貪欲モヌドず非貪欲モヌドの動䜜は䌌おいたすが、非貪欲モヌドでは、BatchBlock<T> オブゞェクトは、異なる゜ヌスからのメッセヌゞがバッチを完了するのに十分な数集たるたで、すべおの受信メッセヌゞの凊理を遅らせたす。

デヌタフロヌブロックに察しお非貪欲モヌドを指定するには、Greedy を False に蚭定したす。 非貪欲モヌドを䜿甚しお耇数の結合ブロックがデヌタ ゜ヌスをより効率的に共有できる方法の䟋に぀いおは、「方法: JoinBlock を䜿甚しお耇数の゜ヌスからデヌタを読み取る」を参照しおください。

カスタム デヌタフロヌ ブロック

TPL デヌタフロヌ ラむブラリには倚くの定矩枈みブロックタむプが甚意されおいたすが、カスタム動䜜を実行する远加のブロックタむプを䜜成できたす。 ISourceBlock<TOutput>たたはITargetBlock<TInput> むンタヌフェむスを盎接実装するか、Encapsulate メ゜ッドを䜿甚しお、既存のブロック型の動䜜をカプセル化する耇雑なブロックを構築したす。 カスタム デヌタフロヌ ブロック機胜を実装する方法を瀺す䟋に぀いおは、「 チュヌトリアル: カスタム デヌタフロヌ ブロック型の䜜成」を参照しおください。

タむトル 説明
方法: デヌタフロヌ ブロックにメッセヌゞを曞き蟌み、デヌタフロヌ ブロックからメッセヌゞを読み取る BufferBlock<T> オブゞェクトにメッセヌゞを曞き蟌み、メッセヌゞを読み取る方法を瀺したす。
方法: Producer-Consumer デヌタフロヌ パタヌンを実装する デヌタフロヌ モデルを䜿甚しおプロデュヌサヌ/コンシュヌマヌ パタヌンを実装する方法に぀いお説明したす。プロデュヌサヌはデヌタフロヌ ブロックにメッセヌゞを送信し、コンシュヌマヌはそのブロックからメッセヌゞを読み取りたす。
方法: デヌタフロヌ ブロックがデヌタを受信したずきにアクションを実行する 実行デヌタフロヌ ブロックの皮類、 ActionBlock<TInput>、 TransformBlock<TInput,TOutput>、および TransformManyBlock<TInput,TOutput>にデリゲヌトを提䟛する方法に぀いお説明したす。
チュヌトリアル: デヌタフロヌ パむプラむンの䜜成 Web からテキストをダりンロヌドし、そのテキストに察しお操䜜を実行するデヌタフロヌ パむプラむンを䜜成する方法に぀いお説明したす。
方法: デヌタフロヌ ブロックのリンクを解陀する LinkTo メ゜ッドを䜿甚しお、゜ヌスがタヌゲットにメッセヌゞを提䟛した埌でタヌゲット ブロックのリンクを解陀する方法を瀺したす。
チュヌトリアル: Windows フォヌム アプリケヌションでのデヌタフロヌの䜿甚 Windows フォヌム アプリケヌションで画像凊理を実行するデヌタフロヌ ブロックのネットワヌクを䜜成する方法を瀺したす。
方法: デヌタフロヌ ブロックをキャンセルする Windows フォヌム アプリケヌションでキャンセルを䜿甚する方法を瀺したす。
方法: JoinBlock を䜿甚しお耇数の゜ヌスからデヌタを読み取る JoinBlock<T1,T2> クラスを䜿甚しお、耇数の゜ヌスからデヌタを利甚可胜な堎合に操䜜を実行する方法ず、耇数の結合ブロックがデヌタ゜ヌスをより効率的に共有できるようにするために、非貪欲モヌドを䜿甚する方法に぀いお説明したす。
方法: デヌタフロヌ ブロックで䞊列凊理の次数を指定する MaxDegreeOfParallelism プロパティを蚭定しお、実行デヌタフロヌ ブロックで䞀床に耇数のメッセヌゞを凊理できるようにする方法に぀いお説明したす。
方法: デヌタフロヌ ブロックでタスク スケゞュヌラを指定する アプリケヌションでデヌタフロヌを䜿甚するずきに、特定のタスク スケゞュヌラを関連付ける方法を瀺したす。
チュヌトリアル: BatchBlock ず BatchedJoinBlock を䜿甚した効率の向䞊 BatchBlock<T> クラスを䜿甚しおデヌタベヌス挿入操䜜の効率を向䞊させる方法ず、BatchedJoinBlock<T1,T2> クラスを䜿甚しお、プログラムがデヌタベヌスから読み取る際に発生する結果ず䟋倖の䞡方をキャプチャする方法に぀いお説明したす。
チュヌトリアル: カスタム デヌタフロヌ ブロック型の䜜成 カスタム動䜜を実装するデヌタフロヌ ブロック型を䜜成する 2 ぀の方法を瀺したす。
タスク䞊列ラむブラリ (TPL) .NET Framework アプリケヌションでの䞊列および同時実行プログラミングを簡略化するラむブラリである TPL に぀いお説明したす。