在我的应用程序中,我必须侦听多个不同的队列并反序列化/分派在队列上收到的传入消息。
实际上,我要做的是每个QueueConnector对象在构造时创建一个新线程,它执行一个无限循环,对queue.Receive()进行阻塞调用,以接收代码公开的队列中的下一条消息下面:
// Instantiate message pump thread
msmqPumpThread = new Thread(() => while (true)
{
// Blocking call (infinite timeout)
// Wait for a new message to come in queue and get it
var message = queue.Receive();
// Deserialize/Dispatch message
DeserializeAndDispatchMessage(message);
}).Start();
我想知道是否可以使用Task替换此“消息泵”,而不是在新线程上进行无限循环。
我已经为消息接收部分创建了一个任务(见下文),但我真的没有看到如何将它用于消息泵(我可以一次又一次地重新调用相同的任务,继续,替换单独线程中的无限循环,如上面的代码?)
Task<Message> GetMessageFromQueueAsync()
{
var tcs = new TaskCompletionSource<Message>();
ReceiveCompletedEventHandler receiveCompletedHandler = null;
receiveCompletedHandler = (s, e) =>
{
queue.ReceiveCompleted -= receiveCompletedHandler;
tcs.SetResult(e.Message);
};
queue.BeginReceive();
return tcs.Task;
}
在此上下文中,通过在单独的线程中使用Tasks而不是无限循环(使用阻塞调用=&gt;阻塞线程),我会获得任何收益吗?如果是的话,如何正确地做到这一点?
请注意,此应用程序没有很多QueueConnector对象,并且没有(可能有10个连接器MAX),这意味着第一个解决方案中最多有10个Threads,因此内存占用/性能启动线程不是问题这里。我正在考虑调度性能/ CPU使用率。会有什么不同吗?
答案 0 :(得分:0)
当线程数低时,您通常会有更多的开销和更少的异步代码吞吐量。当线程数非常高导致a)由于堆栈和b)上下文切换而浪费大量内存时,非阻塞代码最有用。它有明显的开销,因为更多的分配,更多的间接和更多的用户内核转换。
对于低线程数(<100),您可能不必担心。尝试专注于编写可维护,防错和简单的代码。使用线程。