QueueUtil为MessageHandlers生成了太多线程,异步/等待问题

时间:2019-03-26 19:55:34

标签: multithreading azure async-await azureservicebus azure-servicebus-queues

更新: 错误是在实际任务中使用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);
                }
            );

以某种方式,所有这些异步/等待的东西,我的接收者只要消息到达就一直保持生成线程。

1 个答案:

答案 0 :(得分:0)

错误是在实际任务中使用Action<QueueMessage> onSuccess并在没有await的情况下调用它。实际上,我们正在传递一个async回调作为onSuccess,因此它没有被阻塞,它只是被触发而没有等待它。将类型更改为Func<QueueMessage, Task>并通过await onSuccess(messageObj)进行调用可以解决此问题。