首页 > 解决方案 > 始终运行的任务中的异常处理

问题描述

经过无数小时的测试、搜索和提出问题后,我仍然被困在“始终运行”的任务上,还是在异步 io/并行编程中不存在?

目前我有一个程序可以轮询 webapi 服务(soap)以获取传感器的状态(基于物联网)。

我们编程的层次结构只是扁平化,step1 然后 step2 然后 step3 等等。

现在这里的问题是,如果第 3 步失败并出现异常,第 4-6 步将不会被执行。

所以我想把任务分开,每个任务都有对应的任务。例如; 第 1 步启动程序连接到 webapi,第 2 步获取内存中的传感器列表,第 3 步启动任务。

有 3 个主要任务:1 个任务用于获取传感器的状态,另一个任务是检查网络服务器是否在线,最后一个任务是询问服务器是否有旧传感器的新传感器被删除。

所以第 4 步到第 6 步是 3 个任务。-> 这些任务将始终运行,因为只是轮询服务器,这发生在计时器滴答声上

每 1 秒第 4 步,每 10 秒第 5 步,每分钟第 6 步。

到目前为止还不错,我可能会调用 var task1 = Task.Run( () => somevoidtask);

问题:如果其中一项任务失败,需要重新启动,如何处理?我正在测试并遇到autoresetevent。我将如何处理异常(被记录)并重新启动该任务?

在微软文档上,我经常看到:

var task = Task.Run();
task.wait();
if(task.status == task.faulted)
{
  get exception
}

只是简单的伪。

我目前的测试项目我有这个:

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

namespace taskTest
{
    public class Program
    {
        public static void Main(string[] args)
        {

            var source = new CancellationTokenSource(20000);
            var source2 = new CancellationTokenSource();
            var source3 = new CancellationTokenSource();

            var token1 = source.Token;
            var token2 = source2.Token;
            var token3 = source3.Token;

            Task1(token1);
            Task2(token2);
            Task3(token3);

            Console.ReadLine();

        }





        private static void Task1(CancellationToken token)
        {
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("Cancellation is request for this task.");
                    return;
                }
                Task.Delay(1000);
            }
        }

        private static void Task2(CancellationToken token)
        {
            while (!token.IsCancellationRequested)
            {
                try
                {
                    throw new NullReferenceException();
                }
 

           catch (Exception ex)
            {
                
            }
        }
        Console.WriteLine("Task2 is cancelled");
    }

    private static void Task3(CancellationToken token)
    {
        Task.Run(async () =>
        {
            while (!token.IsCancellationRequested)
            {
                Console.WriteLine($"Task3: getting executed every 10 second");
                await Task.Delay(10000);
            }
            Console.WriteLine("Task3 is cancelled");
        });
    }
}

}

也可能是一个最佳实践,我认为并非我的所有代码都是好的。

标签: c#.net-4.6

解决方案


异常可能很棘手,因为很难知道它们是否使程序处于不可恢复的状态。如果发生这种情况,最好的办法是让您的程序崩溃并依靠外部系统重新启动它。

对于您有理由确定可以安全继续的异常,只需捕获它们,记录并继续。或执行所需的任何其他恢复过程。

我不喜欢你的任何例子。Task1/2 只会阻塞直到被取消,并且只有 task2 有任何类型的异常处理。

对于重复发生的任务,我会推荐一个计时器,Task.Delay无论如何,使用类似的东西只是一个围绕计时器的异步包装器。如果您确定没有线程安全问题,请使用在后台线程上触发的线程。处理您认为可以在计时器的事件处理程序中安全捕获的所有异常,考虑添加一个未处理的异常处理程序以在关闭应用程序之前记录任何其他异常。使您的应用程序成为服务是让 Windows 处理在应用程序失败时重新启动应用程序的一种不错的方法。


推荐阅读