【发布时间】:2017-02-12 03:05:31
【问题描述】:
我正在使用 BeginnReceive 方法和 ReceiveCompleted 事件处理程序来侦听和处理来自 MSMQ 的消息。
我已将 BeginReceive 方法放在 ReceiveCompleted 事件处理程序的开头。
看起来它在我的控制台应用程序中运行良好。 现在,消息是异步处理的。
问题:
关于线程安全,这是否安全?
我看到的所有示例都将 BeginReceive 调用置于已完成事件处理程序的末尾。所以我问自己把它放在完成的处理程序的最开始有什么问题吗?
private void InitializeQueue()
{
try
{
_mq = MessageQueue.GetPrivateQueuesByMachine(_queueServerName).Where(qu => qu.Path == _queueAddress).FirstOrDefault();
_mq.Formatter = new BinaryMessageFormatter();
_mq.ReceiveCompleted += MessageReceiveCompleted;
}
catch (Exception ex)
{
Trace.WriteLine("Failed to initialize Queue!" + Environment.NewLine + " Error:" + Environment.NewLine + ex.Message);
throw;
}
}
async void MessageReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
_mq.BeginReceive();
try
{
await ProcessMessageAsync(e.Message);
}
catch (Exception ex)
{
Trace.WriteLine("Error occured during report fetching:" + Environment.NewLine + ex.Message);
throw;
}
}
【问题讨论】:
-
代码中的多线程访问在哪里,以了解和衡量影响
-
BeginReceive 用于异步处理以在队列中有消息时引发 ReceiveCompleted 事件。在涉及异步问题时,我不是那么多才多艺..所以我最好在遇到麻烦之前问一下..
-
如果订单很重要,我可以将 BeginReceive 放在最后并使用
Task.Run... 调用 ProcessMessageAsync... -
你的理解不正确,
Async-Await依赖于基于硬件的并发机制IO完成端口。这没有任何软件线程,但仍然在后台并发。直到您创建 3 个或更多Async调用,await为所有使用Task.WhenAll的调用,返回复合Task,在执行开始后,它们将以并发模式执行。在您粘贴的代码中,我没有发现任何多线程问题,单个对象mq,注册事件,发布通知,它同步执行BeginReceive,然后在异步模式下等待 Web 服务调用 -
另请注意,Web 服务是一个 IO 调用,通过
Task.Run调用将没有什么用处,因为用于计算处理的线程只会等待 IO 调用返回。在您的完整代码 sn-p 中,我看不到多个线程,这可能会导致竞争条件或损坏等问题
标签: c# asynchronous async-await msmq