我有一个多线程的Windows服务,它使用Rabbit队列消息并根据消息内容发送电子邮件。
在启动时初始化Rabbit客户端时,它会使用最小值和最大值限制Threadpool线程。
对于从队列中取出的每条消息,服务正在使用HttpClient
GetAsync
方法向Web api服务发送HTTP请求以检索电子邮件地址。
问题是请求转到数据服务,但响应永远不会回来。 Windows服务不断消耗队列中的消息并在一段时间后挂起(可能是自由线程的运行) - 它正在等待任何对web api的调用完成,这是他们从未做过的。
我能够使用Semaphore
类为Rabbit循环解决问题,而不是试图直接限制Threadpool,但是,我想知道为什么服务首先进入这个状态。这与GetAsync
电话有关吗?是否可能在请求期间释放线程,以便主循环可以窃取它以用于下一个请求?
有什么想法吗?
原始循环:
while (!_stopped)
{
if (_paused) continue;
try
{
using (var messageBusReceiver = _rabbitQueueClient.ConfigureMessageBusReceiver())
{
using (_consumer = messageBusReceiver.Listen<PublishableItem>())
{
while (!_stopped)
{
if (_paused) continue;
_consumer.Consume(callback, consumeSynchronously: false);
_communicationErrorCount = 0;
}
}
}
}
Consume
方法最终会这样做:
_threadPoolProvider.QueueUserWorkItem(o =>
consumeMessage(callback, eventArgs, o), message);
回调从以下行开始 - 永远不会到达空检查行:
var foo = _fooService.GetFoo(messageInfo.FooId);
if (foo == null)
{
throw new FooNotFoundException(
String.Format(CultureInfo.InvariantCulture, "Foo was not found for FooId of {0}", messageInfo.FooId));
}
客户端方法:
public Foo GetFoo(Guid id)
{
var path = getPathWithQueryStringAndDebug("getfoo", "id", id.ToString());
var response = _client.GetAsync(path).Result;
return processResponse<FooDto>(response);
}