我有一个多线程 Windows 服务,它从 Rabbit 队列中消耗消息并根据消息的内容发送电子邮件。
当 rabbit 客户端在启动时初始化时,它使用 Min 和 Max 值限制 Threadpool 线程。
HttpClient
GetAsync
对于从队列中取出的每条消息,该服务使用检索电子邮件地址的方法向Web api 服务发送 HTTP 请求。
问题是请求发送到数据服务,但响应永远不会回来。Windows 服务不断消耗队列中的消息并在一段时间后挂起(可能是空闲线程的运行) - 它正在等待对 web api 的任何调用完成,而他们从未这样做过。
我能够使用Semaphore
Rabbit 循环的类来解决问题,而不是尝试直接限制线程池,但是,我想知道为什么服务首先会进入这种状态。跟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);
回调从以下几行开始 - 从未到达 null 检查行:
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);
}