使用 Azure 队列时 Web API 未启动

Web API does not start when consume Azure queue

当我使用下面的代码时,Web API 没有启动,我没有看到 swagger 页面。你知道为什么吗?当我在ConfigurationServices中注释代码时,Swagger正常启动。我想要正常的行为(意味着从控制器查看所有端点)+ 订阅队列的方法。

public class Startup
{
    static QueueClient queueClient;

    public void ConfigureServices(IServiceCollection services)
    {
        try
        {
            queueClient = new QueueClient("BusConnectionString","QueueName");
            var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = 1,
                AutoComplete = false
            };
            queueClient.RegisterMessageHandler(ReceiveMessagesAsync, messageHandlerOptions);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            Console.ReadKey();
            queueClient.CloseAsync();
        }
    }

    static async Task ReceiveMessagesAsync(Message message, CancellationToken token)
    {
        Console.WriteLine($"Received message: {Encoding.UTF8.GetString(message.Body)}");

        await queueClient.CompleteAsync(message.SystemProperties.LockToken);
    }

    static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
    {
        Console.WriteLine(exceptionReceivedEventArgs.Exception);
        return Task.CompletedTask;
    }
}

在更新的代码下方,我每 5 秒点击一次 DoWork 方法,但我在 ReceiveMessagesAsync 中没有收到任何消息,也没有例外

更新 1:

public class TimedHostedService : IHostedService, IDisposable
{
    static QueueClient queueClient;

    Timer timer;

    readonly IConfiguration configuration;

    public TimedHostedService(IConfiguration configuration)
    {
        this.configuration = configuration;
    }

    public Task StartAsync(CancellationToken stoppingToken)
    {
        timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    }

    void DoWork(object state)
    {
        try
        {
            queueClient = new QueueClient("QueueConnectionString", "QueueName"]);
            var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = 1,
                AutoComplete = false
            };
            queueClient.RegisterMessageHandler(ReceiveMessagesAsync, messageHandlerOptions);
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            queueClient.CloseAsync();
        }

    }

    public Task StopAsync(CancellationToken stoppingToken)
    {

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        timer?.Dispose();
    }

    static async Task ReceiveMessagesAsync(Message message, CancellationToken token)
    {
        Console.WriteLine($"Received message: {Encoding.UTF8.GetString(message.Body)}");

        await queueClient.CompleteAsync(message.SystemProperties.LockToken);
    }

    static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
    {
        Console.WriteLine(exceptionReceivedEventArgs.Exception);
        return Task.CompletedTask;
    }

}

您不应该在启动阶段做长时间的 运行 工作。通过在启动阶段执行 Console.ReadKey() 来执行初始代码块。

漫长的 运行 工作应该在 the background 中完成。但不要使用计时器,因为现在你在每个 tick 上启动一个新的侦听器,然后几乎直接关闭它。试试这个:

public class QueueProcessorService : IHostedService
{
    private QueueClient queueClient;
    
    public Task StartAsync(CancellationToken cancellationToken)
    {
        queueClient = new QueueClient("BusConnectionString", "QueueName");
        var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
        {
            MaxConcurrentCalls = 1,
            AutoComplete = false
        };
        queueClient.RegisterMessageHandler(ReceiveMessagesAsync, messageHandlerOptions);
        
        return Task.CompletedTask;
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        await queueClient.CloseAsync();
    }

    async Task ReceiveMessagesAsync(Message message, CancellationToken token)
    {
        Console.WriteLine($"Received message: {Encoding.UTF8.GetString(message.Body)}");

        await queueClient.CompleteAsync(message.SystemProperties.LockToken);
    }

    Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
    {
        Console.WriteLine(exceptionReceivedEventArgs.Exception);
        return Task.CompletedTask;
    }
}

顺便说一下,您似乎使用的是相当过时的软件包 Microsoft.Azure.ServiceBus 而不是推荐的软件包 (Azure.Messaging.ServiceBus)。