我有一个长时间运行的控制台应用程序(3小时),在某些情况下我需要使用Exception杀死它。杀死此批次的原因是它由运营商监控并由企业调度程序控制。未处理的异常将提醒他们及其在呼叫支持中使用的消息。
理想情况下,我希望后台线程作为TPL任务运行,以检查这些数据库定义的标准,如果遇到则抛出异常以使进程失败。在Task中抛出异常不会杀死主线程。我尝试了以下操作,在主调度程序上运行ContinueWith
任务,但它不会影响main。
static void Main(string[] args)
{
var mainThread = TaskScheduler.Current;
var taskDb = new Task<bool>(RunDb, TaskCreationOptions.LongRunning);
var taskHandle = taskDb.ContinueWith(b => Check(b.Result), mainThread);
taskDb.Start();
//do stuff
}
static bool RunDb()
{
//check database in loop
//if validation failed return false
return false;
}
static void Check(bool successful)
{
//check database in loop
//if validation failed return false
if(!successful)
throw new Exception("batch failed for these reasons...");
}
我唯一可能的解决方案是从ContinueWith
操作中修改全局属性,并从主线程中查询此属性,抛出异常。
我已经很好地浏览了网络,虽然从主要方面取消了线程,但从后台线程中删除主要内容并不是什么。
答案 0 :(得分:2)
您可以在任何地方使用Environment.FailFast
来关闭您的应用程序,但会有异常。这也适用于后台线程:
Task.Run(() => Environment.FailFast("Fail", new Exception("batch failed for these reasons...")));
但是,我认为更强大的设计是拥有一个系统范围CancellationToken
,您可以从您的任务中取消,从而优雅地关闭整个应用程序。
答案 1 :(得分:1)
Environment.Exit()
可能是最简单的方法。例如,以下程序将在打印约10个数字后退出,而不是完整的100个。
public static void Main(string[] args)
{
Task.Run(() =>
{
Thread.Sleep(1000);
Console.Out.WriteLine("Something has gone terribly wrong!");
System.Environment.Exit(1);
});
for (int i = 0; i < 100; i++)
{
Console.Out.WriteLine(i);
Thread.Sleep(100);
}
}