ASB MessageReceiver ReceiveAsync崩溃

时间:2018-06-19 22:46:59

标签: c# console .net-core azureservicebus azure-servicebus-topics

环境

  1. Windows 10专业版
  2. .NET Core控制台应用程序

代码

我有一个抽象的消息接收器,看起来像这样。在此代码中,entitySubscription的名称(例如user)。

public class AzureMessageReceiver : ITdlMessageReceiver
{
    private readonly ServiceBusConnection serviceBusConnection;
    private readonly ILogger<AzureMessageReceiver> logger;

    public AzureMessageReceiver(ServiceBusConnection serviceBusConnection, ILogger<AzureMessageReceiver> logger)
    {
        this.serviceBusConnection = serviceBusConnection;
        this.logger = logger;
    }

    public async Task<TdlMessage<T>> ReceiveAsync<T>(string topic, string entity) where T : class
    {
        try
        {
            var subscriptionPath = EntityNameHelper.FormatSubscriptionPath(topic, entity);
            var messageReceiver = new MessageReceiver(serviceBusConnection, subscriptionPath, ReceiveMode.ReceiveAndDelete);
            var message = await messageReceiver.ReceiveAsync();

            if (message == null)
            {
                return null;
            }

            var messageString = Encoding.UTF8.GetString(message.Body);
            return JsonConvert.DeserializeObject<TdlMessage<T>>(messageString);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Error receiving Azure message.");
            return null;
        }
    }
}

注入的ServiceBusConnection的构造如下。 注意::相同的连接初始化有效可以将消息写入相同的TopicSubscription

services.AddSingleton(serviceProvider =>
    new ServiceBusConnection(configuration[$"{DurableCommunicationKey}:AzureConnectionString"]));

更新:这是将调用包装到接收方类的代码,并且是接收消息的控制器:

static async void Receive(ITdlMessageReceiver receiver, ILogger logger)
{
    while (true)
    {
        var message = await receiver.ReceiveAsync<TdlMessage<object>>(topic, entity);
        if (message != null)
        {
            logger.LogDebug($"Message received. Topic: {topic}. Action: {Enum.GetName(typeof(TopicActions), message.Action)}. Message: {JsonConvert.SerializeObject(message)}.");

        }

        Thread.Sleep(sleepTime);
    }
}

问题

每次执行此行var message = await messageReceiver.ReceiveAsync();时,它只会崩溃控制台应用程序。没有Exception,没有Event Viewer中的任何内容。

我尝试过的

  • 使用ASB中的Secondary Connection String
  • 提供messageReceiver.ReceiveAsync(TimeSpan.FromMinutes(1));之类的超时时间
  • 将注入的topic从主题的名称更改为主题的整个URL(例如https://{...}.servicebus.windows.net/{topicName}
  • ReceiveMode更改为PeekLock
  • 锁定ConfigureAwait(false)ReceiveAsync通话。
  • 将超时更改为TimeSpan.Zero注意::这不会不会使应用程序崩溃,但实际上会抛出Exception并被记录。

1 个答案:

答案 0 :(得分:1)

async void应该转换为async Task,并且您应该等待Task.Delay而不是调用Thread.Sleep。如果要异步,则需要一直保持异步

static async Task Receive(ITdlMessageReceiver receiver, ILogger logger) {
    while (true) {
        var message = await receiver.ReceiveAsync<TdlMessage<object>>(topic, entity);
        if (message != null) {
            logger.LogDebug($"Message received. Topic: {topic}. Action: {Enum.GetName(typeof(TopicActions), message.Action)}. Message: {JsonConvert.SerializeObject(message)}.");    
        }    
        await Task.Delay(sleepTime);
    }
}

请尝试使代码一直处于异步状态,是的,但是作为控制台应用程序(单线程),您将可以在Wait()的{​​{1}}方法上以以下方式调用Receive:不会混合会导致异步流问题的调用。

Main

引用Async/Await - Best Practices in Asynchronous Programming