更新:
错误是在实际任务中使用Action<QueueMessage> onSuccess
并在没有await
的情况下调用它。实际上,我们正在传递一个async
回调作为onSuccess,因此它没有被阻塞,它只是被触发而没有等待它。将类型更改为Func<QueueMessage, Task>
并通过await onSuccess(messageObj)
进行调用可以解决此问题。
我正在接收消息,并且每条消息都由一项长期运行的作业处理,涉及IO和CPU密集型例程。我的问题是我注册的消息处理程序被调用了太多次(基本上是消息的多次),这使我的进程占用了100%的CPU资源,并且一切都变慢了。
我在QueueClient周围有一个包装器,因此我觉得很麻烦。 我知道我的代码是错误的,但是我对.NET中async / await的工作方式缺乏足够的了解,无法自己修复。
这是包装器代码,它获取json消息或指向Azure存储的链接,因此它处理此逻辑并将其传递给回调。
public static void RegisterReceiver(string queueName,
Action<QueueMessage> onSuccess, Action<ExceptionReceivedEventArgs> onError)
_queueClient.RegisterMessageHandler(
async (message, cancellationToken) =>
{
var messageObj = new QueueMessage(message);
var regex = new Regex(@"\[blob%([^\]]+)\](.+)");
if (regex.IsMatch(messageObj.Body))
{
// Pulling blob data from storage
var match = regex.Match(messageObj.Body);
messageObj.ContentType = match.Groups[1].Value;
messageObj.Body = await BlobUtil.GetAndDeleteBlobAsync(match.Groups[2].Value, settings.QueueBlobStorageName);
}
onSuccess(messageObj);
},
new MessageHandlerOptions((exceptionArgs) =>
{
onError(exceptionArgs);
return Task.CompletedTask;
})
{
MaxConcurrentCalls = 1
}
);
这是带有最终回调的调用代码:
QueueUtil.RegisterReceiver(QueueUtil.QUEUE_NAME,
async message =>
{
await processService.RunJobs(message);
},
exceptionArgs =>
{
throw new Exception("Exception occurred while receiving message from " + QueueUtil.QUEUE_NAME,
exceptionArgs.Exception);
}
);
以某种方式,所有这些异步/等待的东西,我的接收者只要消息到达就一直保持生成线程。
答案 0 :(得分:0)
错误是在实际任务中使用Action<QueueMessage> onSuccess
并在没有await
的情况下调用它。实际上,我们正在传递一个async
回调作为onSuccess,因此它没有被阻塞,它只是被触发而没有等待它。将类型更改为Func<QueueMessage, Task>
并通过await onSuccess(messageObj)
进行调用可以解决此问题。