使用TPL Task杀死.net控制台应用程序

时间:2015-03-24 17:38:56

标签: c# .net multithreading task-parallel-library task

我有一个长时间运行的控制台应用程序(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操作中修改全局属性,并从主线程中查询此属性,抛出异常。

我已经很好地浏览了网络,虽然从主要方面取消了线程,但从后台线程中删除主要内容并不是什么。

2 个答案:

答案 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);
    }
}
相关问题