Procedure: Berichten schrijven en lezen vanuit een gegevensstroomblok
In dit artikel wordt beschreven hoe u de TPL-gegevensstroombibliotheek (Task Parallel Library) gebruikt om berichten te schrijven naar en te lezen vanuit een gegevensstroomblok. De TPL-gegevensstroombibliotheek biedt zowel synchrone als asynchrone methoden voor het schrijven van berichten naar en het lezen van berichten uit een gegevensstroomblok. In dit artikel wordt beschreven hoe u de System.Threading.Tasks.Dataflow.BufferBlock<T> klasse gebruikt. De BufferBlock<T> klasse buffert berichten en gedraagt zich als zowel een berichtbron als een berichtdoel.
Notitie
De TPL-gegevensstroombibliotheek (de System.Threading.Tasks.Dataflow naamruimte) wordt niet gedistribueerd met .NET. Als u de System.Threading.Tasks.Dataflow naamruimte in Visual Studio wilt installeren, opent u uw project, kiest u NuGet-pakketten beheren in het menu Project en zoekt u online naar het System.Threading.Tasks.Dataflow
pakket. U kunt het ook installeren met behulp van de .NET Core CLI.dotnet add package System.Threading.Tasks.Dataflow
Synchroon schrijven en lezen
In het volgende voorbeeld wordt de Post methode gebruikt om te schrijven naar een BufferBlock<T> gegevensstroomblok en de Receive methode om uit hetzelfde object te lezen.
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
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
U kunt ook de TryReceive methode gebruiken om een gegevensstroomblok te lezen, zoals wordt weergegeven in het volgende voorbeeld. De TryReceive methode blokkeert de huidige thread niet en is handig wanneer u af en toe pollt naar gegevens.
// Post more messages to the block.
for (int i = 0; i < 3; i++)
{
bufferBlock.Post(i);
}
// Receive the messages back from the block.
while (bufferBlock.TryReceive(out int value))
{
Console.WriteLine(value);
}
// Output:
// 0
// 1
// 2
' Post more messages to the block.
For i As Integer = 0 To 2
bufferBlock.Post(i)
Next i
' Receive the messages back from the block.
Dim value As Integer
Do While bufferBlock.TryReceive(value)
Console.WriteLine(value)
Loop
' Output:
' 0
' 1
' 2
Omdat de Post methode synchroon werkt, ontvangt het BufferBlock<T> object in de vorige voorbeelden alle gegevens voordat de tweede lus gegevens leest. In het volgende voorbeeld wordt het eerste voorbeeld uitgebreid met behulp van het gelijktijdig Task.WhenAll(Task[]) lezen van en schrijven naar het berichtblok. Omdat WhenAll alle asynchrone bewerkingen die gelijktijdig worden uitgevoerd, worden de waarden niet in een specifieke volgorde naar het BufferBlock<T> object geschreven.
// Write to and read from the message block concurrently.
var post01 = Task.Run(() =>
{
bufferBlock.Post(0);
bufferBlock.Post(1);
});
var receive = Task.Run(() =>
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine(bufferBlock.Receive());
}
});
var post2 = Task.Run(() =>
{
bufferBlock.Post(2);
});
await Task.WhenAll(post01, receive, post2);
// Output:
// 0
// 1
// 2
' Write to and read from the message block concurrently.
Dim post01 = Task.Run(Sub()
bufferBlock.Post(0)
bufferBlock.Post(1)
End Sub)
Dim receive = Task.Run(Sub()
For i As Integer = 0 To 2
Console.WriteLine(bufferBlock.Receive())
Next i
End Sub)
Dim post2 = Task.Run(Sub() bufferBlock.Post(2))
Task.WaitAll(post01, receive, post2)
' Output:
' 0
' 1
' 2
Asynchroon schrijven en lezen
In het volgende voorbeeld wordt de SendAsync methode gebruikt om asynchroon naar een BufferBlock<T> object te schrijven en de ReceiveAsync methode om asynchroon uit hetzelfde object te lezen. In dit voorbeeld worden de asynchrone operators (Async and Await in Visual Basic) gebruikt om asynchroon gegevens te verzenden naar en te lezen uit het doelblok. De SendAsync methode is handig wanneer u een gegevensstroomblok moet inschakelen om berichten uit te stellen. De ReceiveAsync methode is handig wanneer u actie wilt ondernemen op gegevens wanneer die gegevens beschikbaar komen. Zie de sectie Bericht doorgeven in gegevensstroom voor meer informatie over hoe berichten worden doorgegeven tussen berichtblokken.
// Post more messages to the block asynchronously.
for (int i = 0; i < 3; i++)
{
await bufferBlock.SendAsync(i);
}
// Asynchronously receive the messages back from the block.
for (int i = 0; i < 3; i++)
{
Console.WriteLine(await bufferBlock.ReceiveAsync());
}
// Output:
// 0
// 1
// 2
' Post more messages to the block asynchronously.
For i As Integer = 0 To 2
await bufferBlock.SendAsync(i)
Next i
' Asynchronously receive the messages back from the block.
For i As Integer = 0 To 2
Console.WriteLine(await bufferBlock.ReceiveAsync())
Next i
' Output:
' 0
' 1
' 2
Een volledig voorbeeld
In het volgende voorbeeld ziet u alle code voor dit artikel.
using System;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
// Demonstrates a how to write to and read from a dataflow block.
class DataflowReadWrite
{
// Demonstrates asynchronous dataflow operations.
static async Task AsyncSendReceive(BufferBlock<int> bufferBlock)
{
// Post more messages to the block asynchronously.
for (int i = 0; i < 3; i++)
{
await bufferBlock.SendAsync(i);
}
// Asynchronously receive the messages back from the block.
for (int i = 0; i < 3; i++)
{
Console.WriteLine(await bufferBlock.ReceiveAsync());
}
// Output:
// 0
// 1
// 2
}
static async Task Main()
{
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
// Post more messages to the block.
for (int i = 0; i < 3; i++)
{
bufferBlock.Post(i);
}
// Receive the messages back from the block.
while (bufferBlock.TryReceive(out int value))
{
Console.WriteLine(value);
}
// Output:
// 0
// 1
// 2
// Write to and read from the message block concurrently.
var post01 = Task.Run(() =>
{
bufferBlock.Post(0);
bufferBlock.Post(1);
});
var receive = Task.Run(() =>
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine(bufferBlock.Receive());
}
});
var post2 = Task.Run(() =>
{
bufferBlock.Post(2);
});
await Task.WhenAll(post01, receive, post2);
// Output:
// 0
// 1
// 2
// Demonstrate asynchronous dataflow operations.
await AsyncSendReceive(bufferBlock);
}
}
Imports System.Threading.Tasks
Imports System.Threading.Tasks.Dataflow
' Demonstrates a how to write to and read from a dataflow block.
Friend Class DataflowReadWrite
' Demonstrates asynchronous dataflow operations.
Private Shared async Function AsyncSendReceive(ByVal bufferBlock As BufferBlock(Of Integer)) As Task
' Post more messages to the block asynchronously.
For i As Integer = 0 To 2
await bufferBlock.SendAsync(i)
Next i
' Asynchronously receive the messages back from the block.
For i As Integer = 0 To 2
Console.WriteLine(await bufferBlock.ReceiveAsync())
Next i
' Output:
' 0
' 1
' 2
End Function
Shared Sub Main(ByVal args() As String)
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
' Post more messages to the block.
For i As Integer = 0 To 2
bufferBlock.Post(i)
Next i
' Receive the messages back from the block.
Dim value As Integer
Do While bufferBlock.TryReceive(value)
Console.WriteLine(value)
Loop
' Output:
' 0
' 1
' 2
' Write to and read from the message block concurrently.
Dim post01 = Task.Run(Sub()
bufferBlock.Post(0)
bufferBlock.Post(1)
End Sub)
Dim receive = Task.Run(Sub()
For i As Integer = 0 To 2
Console.WriteLine(bufferBlock.Receive())
Next i
End Sub)
Dim post2 = Task.Run(Sub() bufferBlock.Post(2))
Task.WaitAll(post01, receive, post2)
' Output:
' 0
' 1
' 2
' Demonstrate asynchronous dataflow operations.
AsyncSendReceive(bufferBlock).Wait()
End Sub
End Class
Volgende stappen
In dit voorbeeld ziet u hoe u rechtstreeks kunt lezen van en schrijven naar een berichtblok. U kunt ook gegevensstroomblokken verbinden met pijplijnen, die lineaire reeksen gegevensstroomblokken zijn, of netwerken, die grafieken van gegevensstroomblokken zijn. In een pijplijn of netwerk worden gegevens asynchroon doorgegeven aan doelen wanneer die gegevens beschikbaar komen. Zie Walkthrough voor een voorbeeld van het maken van een basisgegevensstroompijplijn: Een gegevensstroompijplijn maken. Zie Walkthrough voor een voorbeeld waarin een complexer gegevensstroomnetwerk wordt gemaakt: Gegevensstroom gebruiken in een Windows Forms-toepassing.