重新启动失败的背景服务

发布于 2025-01-29 17:08:00 字数 1192 浏览 3 评论 0原文

因此,我拥有这样的背景服务,看起来像这样。

public class MyBackgroundService: BackgroundService
{ 
    public MyBackgroundService(){}

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        new Thread(() => new MessageHandler().Process(stoppingToken).Start();
        return Task.CompletedTask;
    }      
}

如果过程方法会引发例外,那么无论如何是否可以尝试重新启动 背景服务或创建新的MessageHandler并运行过程?

编辑,反馈和谷歌搜索后,我想这样的事情

protected override Task ExecuteAsync(CancellationToken cancellationToken)
{       
    Task.Run(() => RunConsumer(cancellationToken)).Start();
    return Task.CompletedTask;
}

private void RunConsumer(CancellationToken cancellationToken)
{
    while (true)
    {
        using var scope = _serviceScopeFactory.CreateScope();
        var myConsumer = scope.ServiceProvider.GetRequiredService<IMyConsumer>();

        Task.Run(() => { new Thread(() => myConsumer.Start()).Start(); })
        .ContinueWith(t =>
        {
            if (t.IsFaulted) {/* Log t.Exception and retry x times */}
            if (t.IsCompleted) {/* Should not not happen in my case */}
        });

    }
}

So I have this background service that looks something like this.

public class MyBackgroundService: BackgroundService
{ 
    public MyBackgroundService(){}

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        new Thread(() => new MessageHandler().Process(stoppingToken).Start();
        return Task.CompletedTask;
    }      
}

If the Process-method would throw an Exception, is there anyway to try to restart
the background service or create a new MessageHandler and run Process?

EDIT, After feedback and googling, Im thinking something like this

protected override Task ExecuteAsync(CancellationToken cancellationToken)
{       
    Task.Run(() => RunConsumer(cancellationToken)).Start();
    return Task.CompletedTask;
}

private void RunConsumer(CancellationToken cancellationToken)
{
    while (true)
    {
        using var scope = _serviceScopeFactory.CreateScope();
        var myConsumer = scope.ServiceProvider.GetRequiredService<IMyConsumer>();

        Task.Run(() => { new Thread(() => myConsumer.Start()).Start(); })
        .ContinueWith(t =>
        {
            if (t.IsFaulted) {/* Log t.Exception and retry x times */}
            if (t.IsCompleted) {/* Should not not happen in my case */}
        });

    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

扮仙女 2025-02-05 17:08:00

您可以像这样编写主循环:

protected override Task ExecuteAsync(CancellationToken cancellationToken)
{
    while(!cancellationToken.IsCancellationRequested) 
    {
        try {
            await RunConsumer(cancellationToken);
        }
        catch (Exception e)
        {
            // log exception
        }
        await Task.Delay(TimeSpan.FromSeconds(30)); // To prevent restarting too often
    }
    return Task.CompletedTask;
}

关键点是

  • 通过检查concellationToken.iscancellationRequested,该服务将在请求时停止,例如,当该过程优雅地结束时,
  • 请捕获所有例外并忽略它,并忽略它,因此可以再次运行任务。
  • task.delay确保该过程不会经常重新启动。

runco​​nsumer中,您可以使用

await Task.Run(() => new MessageHandler().Process(stoppingToken).Start());

它通常最好使用异步/等待,因此您不必手动进行延续和错误检查。

You can write main loop like this:

protected override Task ExecuteAsync(CancellationToken cancellationToken)
{
    while(!cancellationToken.IsCancellationRequested) 
    {
        try {
            await RunConsumer(cancellationToken);
        }
        catch (Exception e)
        {
            // log exception
        }
        await Task.Delay(TimeSpan.FromSeconds(30)); // To prevent restarting too often
    }
    return Task.CompletedTask;
}

The key points is

  • By checking cancellationToken.IsCancellationRequested, the service will be stopped when it is requested, e.g. when the process is ending gracefully,
  • Catch all exception and ignore it, so the task can be run again.
  • Task.Delay ensures that the process will not be restarted too often.

In RunConsumer you can just use

await Task.Run(() => new MessageHandler().Process(stoppingToken).Start());

It is usually better to use async/await so you don't have to do the continuation and error-checking manually.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文