c# - 如何在 C# 中监视和重新启动引发异常的任务?

标签 c# .net asynchronous async-await

假设我有一个程序实例化三个无限期运行的任务。这些任务旨在并行运行。但是,假设这些任务偶尔会由于网络错误而引发异常。

监视任务并在必要时重新启动它的最简单技术是什么?

我解决此问题的方法是监视 Task.Status 数据,并在任务发生故障时简单地调用 Task.Start() 方法。

但是,此代码不起作用,因为任务异常会导致整个应用程序崩溃。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var my_task = Program.MainAsync();

            my_task.Wait();
        }


        public static async Task MainAsync()
        {
            var task_1 = Program.TaskMethod("1");
            var task_2 = Program.TaskMethod("2");
            var task_3 = Program.TaskMethod("3");

            // loop indefinitely restarting task if necessary
            while(true)
            {
                if (task_1.Status == TaskStatus.Faulted)
                    task_1.Start();
                if (task_2.Status == TaskStatus.Faulted)
                    task_2.Start();
                if (task_3.Status == TaskStatus.Faulted)
                    task_3.Start();

                await Task.Delay(1000);

            }

        }

        public static async Task TaskMethod(string task_id)
        {
            Console.WriteLine("Starting Task {0}", task_id);
            while(true)
            {
                await Task.Delay(5000);
                Console.WriteLine("Hello from task {0}", task_id);

                int i = 0;
                int b = 32 / i;

            }
        }

    }
}

最佳答案

Task无法重启,可以考虑使用任务工厂Func<Task>每次 Task 时都可以一次又一次地调用它失败,创建更多任务。

List<Func<Task>> taskFactories = new();

taskFactories.Add(() => TaskMethod("1"));
taskFactories.Add(() => TaskMethod("2"));
taskFactories.Add(() => TaskMethod("3"));

Task[] enhancedTasks = taskFactories.Select(async factory =>
{
    while (true)
    {
        try
        {
            Task task = factory();
            await task;
            break; // On success stop
        }
        catch (OperationCanceledException) { throw; } // On cancellation stop
        catch { await Task.Delay(1000); continue; } // On error restart after a delay
    }
}).ToArray();

await Task.WhenAll(enhancedTasks);

每个工厂预计将增强 Task其中包括失败时重新启动功能。 Select LINQ 运算符用于进行投影。


注意:原始答案包含 Task.WhenAny -in-a-loop 反模式,可以在 second revision 中找到这个答案。

关于c# - 如何在 C# 中监视和重新启动引发异常的任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59431924/

相关文章:

c# - Automapper 不填充目标对象

c# - 如何使用 System.Speech.Synthesis 更改音频设备

c# - 将数据与线程 : How do you do that? 相关联

java - Netty 是否违反了 Future.cancel(...) 方法的约定?

c - 避免共享对象中的内部线程

c# - 委托(delegate) - 异常不会等到调用 EndInvoke()

c# - 如何可视化 XAML

.net - 有没有办法识别一个人是否属于 Active Directory 中的指定组,即使该组有几个级别深

c# - ADFS 登录页面本地化 - ASP.NET : I can't seem to be able to change language of the page dynamically

c# - 创建一个在总线上包装订阅和发布的异步方法