.NET basado en eventos:productor/consumidor simultáneo que utiliza una cola asíncrona sin bloqueo

 C Programming >> Programación C >  >> Tags >> .NET
.NET basado en eventos:productor/consumidor simultáneo que utiliza una cola asíncrona sin bloqueo

En un artículo anterior, escribí sobre cómo implementar un productor/consumidor simultáneo usando BlockingCollection. Este es un enfoque seguro para subprocesos y basado en eventos que utiliza construcciones simultáneas de alto nivel. El único inconveniente es que el consumidor utiliza una llamada de bloqueo para sacar los mensajes de la cola. En otras palabras, desperdicia un hilo.

¿Hay alguna manera de implementar esto utilizando un enfoque sin bloqueo?

Sí, usando el Canal clase de System.Threading.Channels. Esto es esencialmente una cola asíncrona.

En este artículo, mostraré cómo usar un Canal para implementar un productor/consumidor simultáneo sin bloqueos.

1:cree un consumidor que use un canal como una cola asíncrona

Nota:Esto está usando System.Threading.Channels.

public class StringReverser
{
	private readonly Channel<string> messageQueue;
	public StringReverser(Channel<string> messageQueue)
	{
		this.messageQueue = messageQueue;
	}
	public async Task StartProcessing(CancellationToken cancelToken)
	{
		await foreach(var message in messageQueue.Reader.ReadAllAsync(cancelToken))
		{
			var reversedString = new string(message.Reverse().ToArray());

			Console.WriteLine($"Thread={Thread.CurrentThread.ManagedThreadId} reverse({message})=>{reversedString}");
		}
	}
	public async Task QueueForProcessing(string Message, CancellationToken cancelToken)
	{
		await messageQueue.Writer.WriteAsync(Message, cancelToken);
	}
}
Code language: C# (cs)

2 – Inicie el Consumidor y comience a producir mensajes

public static async Task Main(string[] args)
{
	var messageQueue = Channel.CreateUnbounded<string>();
	var messageReverser = new StringReverser(messageQueue);

	CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();


	messageReverser.StartProcessing(cancellationTokenSource.Token);

	while (true)
	{
		Console.WriteLine($"Thread={Thread.CurrentThread.ManagedThreadId} Write a sentence and see each word reversed: ");
		var msg = Console.ReadLine();
		Console.WriteLine("");

		foreach (var s in msg.Split())
		{
			await messageReverser.QueueForProcessing(s, cancellationTokenSource.Token);
		}

	}
}
Code language: C# (cs)

3 – Resultados finales:ejecución de la aplicación de consola

Cuando ejecuto esto, puede ver que el consumidor no está bloqueando; de lo contrario, no podría escribir mensajes en la consola.

Además, observe que al principio está usando el subproceso 4, luego, al final, cambia al subproceso 5. Está usando subprocesos de grupo de subprocesos y no está sentado allí desperdiciando un subproceso dedicado. Este es un beneficio clave de este enfoque asíncrono sin bloqueo.