简体   繁体   English

始终运行任务中的异常处理

[英]Exception handling in Always-running tasks

After countless hours of testing,searching, and asking question i'm still stuck on 'always-running' tasks, or does that not exist in async io/ parallell programming?经过无数小时的测试、搜索和提问,我仍然坚持“始终运行”的任务,或者异步 io/并行编程中不存在这种情况?

currently I have a program that polls webapi service (soap) to get status of sensor (IOT based).目前我有一个程序可以轮询 webapi 服务(soap)以获取传感器状态(基于物联网)。

The hiearchy of our programming is just flatten down, step1 then step2 then step3 and so on and so forth.我们编程的层次结构只是扁平化,step1然后step2然后step3等等。

Now the problem here is if step 3 fails with an exception step 4-6 will not be executed.现在的问题是,如果第 3 步失败并出现异常,第 4-6 步将不会执行。

So i had in mind to split up in tasks each with there coresponding task.所以我想把每个任务分成相应的任务。 For instance;例如; step 1 start program connect to webapi, step 2 get a list of sensors in memory, step 3 start tasks.第 1 步启动程序连接到 webapi,第 2 步获取内存中的传感器列表,第 3 步启动任务。

There are 3 main tasks: 1 task for getting the statusses for the sensors, another to check if the webserver is online, and the last one to ask the server if there are new sensors of old one getting deleted.有 3 个主要任务:1 个任务用于获取传感器的状态,另一个任务是检查网络服务器是否在线,最后一个任务是询问服务器是否有旧传感器的新传感器被删除。

so step 4 to step 6 are 3 tasks.所以第 4 步到第 6 步是 3 个任务。 -> these task will always be running since there are just polling the server, this happens on timer ticks -> 这些任务将始终运行,因为只是轮询服务器,这发生在计时器滴答上

step 4 each 1 second, step 5 each 10 seconds, and step 6 every minute.第 4 步每 1 秒,第 5 步每 10 秒,第 6 步每分钟。

Oke so far so good, I probably call var task1 = Task.Run( () => somevoidtask);到目前为止一切顺利,我可能会调用 var task1 = Task.Run( () => somevoidtask);

Question: How to handle here if one of the tasks has failed and needs to be restarted?问题:如果其中一项任务失败需要重新启动,这里如何处理? I was testing around and came across autoresetevent.我正在测试并遇到了 autoresetevent。 How will I handle the exception (gets logged) and restart that task?我将如何处理异常(被记录)并重新启动该任务?

On microsoft docs i commonly see:在微软文档上,我经常看到:

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

just simple pseudo.只是简单的伪。

my current test project I have this:我目前的测试项目我有这个:

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

} }

Also maybe a best practice I assume not all my code is good.也可能是最佳实践,我认为并非所有代码都很好。

Exceptions can be tricky since it can be difficult to know if they have put the program in an unrecoverable state or not.异常可能很棘手,因为很难知道它们是否使程序处于不可恢复的状态。 If that has happened the best thing to do is to let your program crash and rely on an external system to restart it.如果发生这种情况,最好的办法是让您的程序崩溃并依靠外部系统重新启动它。

For exceptions you are reasonably sure are safe to continue from, just catch them, log it, and continue.对于您有理由确定可以安全继续的异常,只需捕获它们,记录它,然后继续。 Or perform any other recovery process needed.或者执行所需的任何其他恢复过程。

I do not like any of your examples.我不喜欢你的任何例子。 Task1/2 will just block until canceled and only task2 have any kind of exception handling. Task1/2 只会阻塞直到被取消并且只有 task2 有任何类型的异常处理。

For reoccurring tasks I would recommend a timer, using things like Task.Delay is just a async-wrapper around a timer anyway.对于重复出现的任务,我会推荐一个计时器, Task.Delay使用Task.Delay东西只是一个围绕计时器的异步包装器。 Use one that triggers on a background thread if you are sure there are no thread safety issues.如果您确定没有线程安全问题,请使用在后台线程上触发的线程。 Handle all exceptions that you consider safe to catch in the event-handler of the timer, consider adding an unhandled exception handler to log any other exceptions before closing your application.在计时器的事件处理程序中处理您认为可以安全捕获的所有异常,考虑在关闭应用程序之前添加未处理的异常处理程序以记录任何其他异常。 Making your application a service is a decent way to let windows deal with restarting your application if it fails.使您的应用程序成为服务是让 Windows 处理在应用程序失败时重新启动应用程序的好方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM