[英]Exception handling in Always-running tasks
经过无数小时的测试、搜索和提问,我仍然坚持“始终运行”的任务,或者异步 io/并行编程中不存在这种情况?
目前我有一个程序可以轮询 webapi 服务(soap)以获取传感器状态(基于物联网)。
我们编程的层次结构只是扁平化,step1然后step2然后step3等等。
现在的问题是,如果第 3 步失败并出现异常,第 4-6 步将不会执行。
所以我想把每个任务分成相应的任务。 例如; 第 1 步启动程序连接到 webapi,第 2 步获取内存中的传感器列表,第 3 步启动任务。
有 3 个主要任务:1 个任务用于获取传感器的状态,另一个任务是检查网络服务器是否在线,最后一个任务是询问服务器是否有旧传感器的新传感器被删除。
所以第 4 步到第 6 步是 3 个任务。 -> 这些任务将始终运行,因为只是轮询服务器,这发生在计时器滴答上
第 4 步每 1 秒,第 5 步每 10 秒,第 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");
});
}
}
}
也可能是最佳实践,我认为并非所有代码都很好。
异常可能很棘手,因为很难知道它们是否使程序处于不可恢复的状态。 如果发生这种情况,最好的办法是让您的程序崩溃并依靠外部系统重新启动它。
对于您有理由确定可以安全继续的异常,只需捕获它们,记录它,然后继续。 或者执行所需的任何其他恢复过程。
我不喜欢你的任何例子。 Task1/2 只会阻塞直到被取消并且只有 task2 有任何类型的异常处理。
对于重复出现的任务,我会推荐一个计时器, Task.Delay
使用Task.Delay
东西只是一个围绕计时器的异步包装器。 如果您确定没有线程安全问题,请使用在后台线程上触发的线程。 在计时器的事件处理程序中处理您认为可以安全捕获的所有异常,考虑在关闭应用程序之前添加未处理的异常处理程序以记录任何其他异常。 使您的应用程序成为服务是让 Windows 处理在应用程序失败时重新启动应用程序的好方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.