Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este documento se describe cómo establecer la ExecutionDataflowBlockOptions.MaxDegreeOfParallelism propiedad para permitir que un bloque de flujo de datos de ejecución procese más de un mensaje cada vez. Esto resulta útil cuando tiene un bloque de flujo de datos que realiza un cálculo de larga duración y puede beneficiarse del procesamiento de mensajes en paralelo. En este ejemplo se usa la System.Threading.Tasks.Dataflow.ActionBlock<TInput> clase para realizar varias operaciones de flujo de datos simultáneamente; sin embargo, puede especificar el grado máximo de paralelismo en cualquiera de los tipos de bloques de ejecución predefinidos que proporciona la biblioteca de flujos de datos de TPL, ActionBlock<TInput>, System.Threading.Tasks.Dataflow.TransformBlock<TInput,TOutput>y System.Threading.Tasks.Dataflow.TransformManyBlock<TInput,TOutput>.
Nota:
La biblioteca TPL Dataflow (el espacio de nombres System.Threading.Tasks.Dataflow) no se distribuye con .NET. Para instalar el System.Threading.Tasks.Dataflow espacio de nombres en Visual Studio, abra su proyecto, elija Administrar paquetes NuGet en el menú Proyecto y busque en línea el paquete System.Threading.Tasks.Dataflow
. Como otra opción, para instalarlo mediante la CLI de .NET Core, ejecute dotnet add package System.Threading.Tasks.Dataflow
.
Ejemplo
En el ejemplo siguiente se realizan dos cálculos de flujo de datos y se imprime el tiempo transcurrido necesario para cada cálculo. El primer cálculo especifica un grado máximo de paralelismo de 1, que es el valor predeterminado. Un grado máximo de paralelismo de 1 hace que el bloque de flujo de datos procese los mensajes en serie. El segundo cálculo es similar al primero, salvo que especifica un grado máximo de paralelismo que es igual al número de procesadores disponibles. Esto permite que el bloque de flujo de datos realice varias operaciones en paralelo.
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks.Dataflow;
// Demonstrates how to specify the maximum degree of parallelism
// when using dataflow.
class Program
{
// Performs several computations by using dataflow and returns the elapsed
// time required to perform the computations.
static TimeSpan TimeDataflowComputations(int maxDegreeOfParallelism,
int messageCount)
{
// Create an ActionBlock<int> that performs some work.
var workerBlock = new ActionBlock<int>(
// Simulate work by suspending the current thread.
millisecondsTimeout => Thread.Sleep(millisecondsTimeout),
// Specify a maximum degree of parallelism.
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = maxDegreeOfParallelism
});
// Compute the time that it takes for several messages to
// flow through the dataflow block.
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < messageCount; i++)
{
workerBlock.Post(1000);
}
workerBlock.Complete();
// Wait for all messages to propagate through the network.
workerBlock.Completion.Wait();
// Stop the timer and return the elapsed number of milliseconds.
stopwatch.Stop();
return stopwatch.Elapsed;
}
static void Main(string[] args)
{
int processorCount = Environment.ProcessorCount;
int messageCount = processorCount;
// Print the number of processors on this computer.
Console.WriteLine($"Processor count = {processorCount}.");
TimeSpan elapsed;
// Perform two dataflow computations and print the elapsed
// time required for each.
// This call specifies a maximum degree of parallelism of 1.
// This causes the dataflow block to process messages serially.
elapsed = TimeDataflowComputations(1, messageCount);
Console.WriteLine("Degree of parallelism = {0}; message count = {1}; " +
"elapsed time = {2}ms.", 1, messageCount, (int)elapsed.TotalMilliseconds);
// Perform the computations again. This time, specify the number of
// processors as the maximum degree of parallelism. This causes
// multiple messages to be processed in parallel.
elapsed = TimeDataflowComputations(processorCount, messageCount);
Console.WriteLine("Degree of parallelism = {0}; message count = {1}; " +
"elapsed time = {2}ms.", processorCount, messageCount, (int)elapsed.TotalMilliseconds);
}
}
/* Sample output:
Processor count = 4.
Degree of parallelism = 1; message count = 4; elapsed time = 4032ms.
Degree of parallelism = 4; message count = 4; elapsed time = 1001ms.
*/
Imports System.Diagnostics
Imports System.Threading
Imports System.Threading.Tasks.Dataflow
' Demonstrates how to specify the maximum degree of parallelism
' when using dataflow.
Friend Class Program
' Performs several computations by using dataflow and returns the elapsed
' time required to perform the computations.
Private Shared Function TimeDataflowComputations(ByVal maxDegreeOfParallelism As Integer, ByVal messageCount As Integer) As TimeSpan
' Create an ActionBlock<int> that performs some work.
Dim workerBlock = New ActionBlock(Of Integer)(Function(millisecondsTimeout) Pause(millisecondsTimeout), New ExecutionDataflowBlockOptions() With {.MaxDegreeOfParallelism = maxDegreeOfParallelism})
' Simulate work by suspending the current thread.
' Specify a maximum degree of parallelism.
' Compute the time that it takes for several messages to
' flow through the dataflow block.
Dim stopwatch As New Stopwatch()
stopwatch.Start()
For i As Integer = 0 To messageCount - 1
workerBlock.Post(1000)
Next i
workerBlock.Complete()
' Wait for all messages to propagate through the network.
workerBlock.Completion.Wait()
' Stop the timer and return the elapsed number of milliseconds.
stopwatch.Stop()
Return stopwatch.Elapsed
End Function
Private Shared Function Pause(ByVal obj As Object)
Thread.Sleep(obj)
Return Nothing
End Function
Shared Sub Main(ByVal args() As String)
Dim processorCount As Integer = Environment.ProcessorCount
Dim messageCount As Integer = processorCount
' Print the number of processors on this computer.
Console.WriteLine("Processor count = {0}.", processorCount)
Dim elapsed As TimeSpan
' Perform two dataflow computations and print the elapsed
' time required for each.
' This call specifies a maximum degree of parallelism of 1.
' This causes the dataflow block to process messages serially.
elapsed = TimeDataflowComputations(1, messageCount)
Console.WriteLine("Degree of parallelism = {0}; message count = {1}; " & "elapsed time = {2}ms.", 1, messageCount, CInt(Fix(elapsed.TotalMilliseconds)))
' Perform the computations again. This time, specify the number of
' processors as the maximum degree of parallelism. This causes
' multiple messages to be processed in parallel.
elapsed = TimeDataflowComputations(processorCount, messageCount)
Console.WriteLine("Degree of parallelism = {0}; message count = {1}; " & "elapsed time = {2}ms.", processorCount, messageCount, CInt(Fix(elapsed.TotalMilliseconds)))
End Sub
End Class
' Sample output:
'Processor count = 4.
'Degree of parallelism = 1; message count = 4; elapsed time = 4032ms.
'Degree of parallelism = 4; message count = 4; elapsed time = 1001ms.
'
Programación sólida
De forma predeterminada, cada bloque de flujo de datos predefinido propaga los mensajes en el orden en que se reciben los mensajes. Aunque se procesan varios mensajes simultáneamente cuando se especifica un grado máximo de paralelismo mayor que 1, todavía se propagan en el orden en que se reciben.
Dado que la propiedad #D0 representa el grado máximo de paralelismo, el bloque de flujo de datos puede ejecutarse con un menor grado de paralelismo que el especificado. El bloque de flujo de datos puede usar un menor grado de paralelismo para cumplir sus requisitos funcionales o para tener en cuenta la falta de recursos del sistema disponibles. Un bloque de flujo de datos nunca elige un mayor grado de paralelismo que el especificado.