c# - ASB MessageReceiver ReceiveAsync 崩溃

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

环境

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

代码

我有一个抽象的消息接收器,如下所示。在此代码中,实体订阅的名称(例如用户)。

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;
        }
    }
}

注入(inject)的ServiceBusConnection是这样构造的。 注意:相同的连接初始化可以将消息写入到相同的主题订阅.

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

更新:以下代码包装了对接收器类的调用,并且是接收消息的 Controller :

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 = wait messageReceiver.ReceiveAsync(); 时,它都会使控制台应用程序崩溃。没有异常事件查看器中也没有任何内容。

我尝试过的

  • 使用 ASB 中的辅助连接字符串
  • 提供超时,例如 messageReceiver.ReceiveAsync(TimeSpan.FromMinutes(1));
  • 将注入(inject)的topic主题名称更改为主题的整个URL(例如https://{...}。 servicebus.windows.net/{topicName})
  • ReceiveMode 更改为 PeekLock
  • ConfigureAwait(false) 添加到 ReceiveAsync 调用中。
  • 将超时更改为 TimeSpan.Zero注意:不会使应用程序崩溃,但实际上会抛出一个被记录的异常

最佳答案

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);
    }
}

尝试使代码始终异步,是的,但作为控制台应用程序(单线程),您将被允许在 Receive 上调用 Wait() Main 中的方法,因为它不会混合调用,从而导致异步流程出现问题。

public static void Main(string[] args) {

    //...
    //...
    //...


    Receive(receiver, logger).Wait();
}

引用Async/Await - Best Practices in Asynchronous Programming

关于c# - ASB MessageReceiver ReceiveAsync 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50937933/

相关文章:

java - 是否可以在启动 .jar 时加载不同的配置文件?

c# - 如何使用 asp.net Core 下载文件?

c# - 将 sqlite 数据库存储在 Visual Studio 和 dotnet 可以看到的位置

c# - 如何获取 List<object> 的单个值

c++ - 在C++中打印国际象棋unicode字符,并将字符设置为正方形

delphi - XE7 ReadLn 命令中的 UTF8 文本问题

c# - 配置 Strict Cors .Net Core 3.1

c# - 将属性序列化为元素中的 Xml 属性

c# - 根据 List<string[]> 中的数组索引查找值

c# - 在 C# 中绘制桌面