【发布时间】:2016-07-15 16:15:53
【问题描述】:
我正在开发一个服务器端控制台应用程序,该应用程序从多个 WCF 服务接收数据,对其进行一些处理,然后使用 SignalR 通过单个连接将结果转发到 IIS 服务器。
我尝试使用生产者消费者模式来实现这一点,其中 WCF 服务是生产者,使用 SignalR 发送数据的类是消费者。对于队列,我使用了BlockingCollection。
但是,当使用 await/async 在消费者的 while 循环中发送数据时,会卡住,直到所有其他线程完成将数据添加到队列中。
出于测试目的,我已经用Task.Delay(1000).Wait(); 或await Task.Delay(1000); 替换了实际发送数据的代码,它们也都卡住了。
一个简单的Thread.Sleep(1000); 似乎工作得很好,这让我认为异步代码是问题所在。
所以我的问题是:有什么东西阻止异步代码在 while 循环中完成吗?我错过了什么?
我正在像这样启动消费者线程:
new Thread(Worker).Start();
以及消费者代码:
private void Worker()
{
while (!_queue.IsCompleted)
{
IMobileMessage msg = null;
try
{
msg = _queue.Take();
}
catch (InvalidOperationException)
{
}
if (msg != null)
{
try
{
Trace.TraceInformation("Sending: {0}", msg.Name);
Thread.Sleep(1000); // <-- works
//Task.Delay(1000).Wait(); // <-- doesn't work
msg.SentTime = DateTime.UtcNow;
Trace.TraceInformation("X sent at {1}: {0}", msg.Name, msg.SentTime);
}
catch (Exception e)
{
TraceException(e);
}
}
}
}
【问题讨论】:
-
阻止和异步不是朋友。如果您将
async与BlockingCollection<T>混合使用,您应该强烈考虑放弃BlockingCollection<T>并查看TPL 数据流。BufferBlock<T>是一个很好的起点,大致相当于BlockingCollection<T>,但数据流可以为生产者/消费者场景提供更多功能。花时间去了解它。这是值得的。 -
好的,非常感谢,我会调查的。
标签: c# .net multithreading asynchronous blockingcollection