您可能会发现this answer非常有帮助 . 我对RabbitMQ的工作原理有了一个非常基本的了解,但我可能会在每个线程的每个通道上继续使用一个用户,正如那里所建议的那样 .
为此组织线程模型肯定有多个选项 . 实际实现将取决于您需要如何处理来自多个队列的消息:并行,或者通过聚合它们并序列化处理 . 以下代码是一个控制台应用程序,它实现了后一种情况的模拟 . 它使用Task Parallel Library和BlockingCollection类(这对于这种任务非常方便) .
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Console_21842880
{
class Program
{
BlockingCollection _commonQueue;
// process an individual queue
void ProcessQueue(int id, BlockingCollection queue, CancellationToken token)
{
while (true)
{
// observe cancellation
token.ThrowIfCancellationRequested();
// get a message, this blocks and waits
var message = queue.Take(token);
// process this message
// just place it to the common queue
var wrapperMessage = "queue " + id + ", message: " + message;
_commonQueue.Add(wrapperMessage);
}
}
// process the common aggregated queue
void ProcessCommonQeueue(CancellationToken token)
{
while (true)
{
// observe cancellation
token.ThrowIfCancellationRequested();
// this blocks and waits
// get a message, this blocks and waits
var message = _commonQueue.Take(token);
// process this message
Console.WriteLine(message.ToString());
}
}
// run the whole process
async Task RunAsync(CancellationToken token)
{
var queues = new List>();
_commonQueue = new BlockingCollection();
// start individual queue processors
var tasks = Enumerable.Range(0, 4).Select((i) =>
{
var queue = new BlockingCollection();
queues.Add(queue);
return Task.Factory.StartNew(
() => ProcessQeueue(i, queue, token),
TaskCreationOptions.LongRunning);
}).ToList();
// start the common queue processor
tasks.Add(Task.Factory.StartNew(
() => ProcessCommonQeueue(token),
TaskCreationOptions.LongRunning));
// start the simulators
tasks.AddRange(Enumerable.Range(0, 4).Select((i) =>
SimulateMessagesAsync(queues, token)));
// wait for all started tasks to complete
await Task.WhenAll(tasks);
}
// simulate a message source
async Task SimulateMessagesAsync(List> queues, CancellationToken token)
{
var random = new Random(Environment.TickCount);
while (true)
{
token.ThrowIfCancellationRequested();
await Task.Delay(random.Next(100, 1000));
var queue = queues[random.Next(0, queues.Count)];
var message = Guid.NewGuid().ToString() + " " + DateTime.Now.ToString();
queue.Add(message);
}
}
// entry point
static void Main(string[] args)
{
Console.WriteLine("Ctrl+C to stop...");
var cts = new CancellationTokenSource();
Console.CancelKeyPress += (s, e) =>
{
// cancel upon Ctrl+C
e.Cancel = true;
cts.Cancel();
};
try
{
new Program().RunAsync(cts.Token).Wait();
}
catch (Exception ex)
{
if (ex is AggregateException)
ex = ex.InnerException;
Console.WriteLine(ex.Message);
}
Console.WriteLine("Press Enter to exit");
Console.ReadLine();
}
}
}
另一个想法可能是使用Reactive Extensions (Rx) . 如果你能想到事件中到达的消息,Rx可以帮助将它们聚合成单个流 .