I have a simplified producer/consumer pattern implemented below. The code outputs:
"A"
1 second delay
"B"
1 second delay
"A"
1 second delay
"B"
...
What approach can I take here to get rid of the 1-second delay between different letters?
What I'm looking for is something like
"A"
"B"
1 second delay
"A"
"B"
...
It's important, that clients A and B receive the messages in the order the messages were queued in, but I do not want other clients to be blocked while processing for one client takes a really long time. Using two BlockingCollections
and two consumer threads is not an option, because the user count is dynamic.
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
namespace ConsumerProducer
{
public enum ClientId
{
A,
B
}
class WebSocketMessage
{
public ClientId ClientId { get; }
public WebSocketMessage(ClientId clientId)
{
ClientId = clientId;
}
public async Task LongRunningSend()
{
Console.WriteLine(ClientId);
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
class Program
{
public static BlockingCollection<WebSocketMessage> Messages = new BlockingCollection<WebSocketMessage>();
static async Task Main(string[] args)
{
var consumer = Task.Run(async () =>
{
foreach (var message in Messages.GetConsumingEnumerable())
{
await message.LongRunningSend();
}
});
ClientId clientId = ClientId.B;
while (true)
{
// Flip between A and B
clientId = clientId == ClientId.A ? ClientId.B : ClientId.A;
Messages.Add(new WebSocketMessage(clientId));
await Task.Delay(TimeSpan.FromMilliseconds(100));
}
}
}
}