c# - 用任务替换无限线程循环(消息泵)

标签 c# asynchronous task-parallel-library producer-consumer

在我的应用程序中,我必须监听多个不同的队列并反序列化/调度队列上收到的传入消息。

实际上,我为实现这一目标所做的是每个 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(s) 代替这个“消息泵”,而不是在新线程上进行无限循环。

我已经为消息接收部分做了一个任务(见下文),但我真的不知道如何将它用于消息泵(我可以一遍又一遍地记忆起相同的任务吗?像上面的代码一样在单独的线程中无限循环?)

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;
}

在此上下文中,通过在单独的线程(使用阻塞调用 => 阻塞线程)中使用任务而不是无限循环,我会得到什么吗?如果是,如何正确执行?

请注意,此应用程序没有很多 QueueConnector 对象,并且不会有(最多可能有 10 个连接器),这意味着通过第一个解决方案最多有 10 个线程,因此内存占用/性能启动线程不是问题这里。我宁愿考虑调度性能/CPU 使用率。会有什么不同吗?

最佳答案

当线程数较少时,异步代码通常会有更多的开销和更少的吞吐量。当线程数量非常多时,非阻塞代码最有用,这会导致 a) 由于堆栈造成大量内存浪费和 b) 上下文切换。但由于更多的分配、更多的间接和更多的用户内核转换,它有明显的开销。

对于低线程数 (< 100),您可能不必担心。尽量专注于编写可维护、防错和简单的代码。使用线程。

关于c# - 用任务替换无限线程循环(消息泵),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11350026/

相关文章:

c# - WP7 上的 Spring IoC?

c# - 如何将 xml 片段解析为节点并将它们附加到具有指定默认 namespace 的节点,以便它们成为该 namespace 的一部分?

ios - 无法从 URL 获取图像以快速更新 UIImage

javascript - 如何在继续之前等待所有文件被读取并执行所有回调

c# - Visual Studio 在我的 web.configs 中看到错误

c# - 用正则表达式替换字符串

c# - 取消自动完成字段的任务不会取消所有以前的任务

c# - 匿名并行任务计时器?

javascript - 执行上下文 : Why would this javascript code behave like this?

C#,阻塞集合 : How to wait until collection has less than N items