c#如何将Task异常传播到主线程

时间:2017-04-05 05:13:37

标签: c# multithreading exception task

我有以下代码 - 我有一个在控制台应用程序的后台永久运行的线程。如果在该任务中抛出异常,我需要传播到主线程。我怎么能这样做?

    private void StartTask()
    {
        Task.Run(() =>
        {

                while (_subStatus)
                {
                 // do work here
                 // an exception might be thrown
                }

        });
    }

编辑: 我不够清楚。该任务旨在运行应用程序的生命周期。它不需要返回结果。我确实想知道然后在任务中抛出异常。它看起来像这样:

    static void Main(string[] args)
    {
       //setup
       StartTask()
       // continue to do other work in the main thread
       while (true)
       {
         // main thread work
       }
    }

EDIT2:使用以下代码我至少可以记录错误

    private async Task StartTask()
    {
       try{
        await Task.Run(() =>
        {

                while (_subStatus)
                {
                 // do work here
                 // an exception might be thrown
                }

        });
        }catch(exception e)
        { //log exception here, still not on the main thread though }
    }

最终编辑: 从底部的答案:https://github.com/Topshelf/Topshelf/issues/245 对于长时间运行的任务(线程),我应该执行以下操作:

new Thread(() => {
// your exception here will stop the service or take down the app
}).Start();

不是这个:

Task.Run(() => {
// your thrown exception here won't stop the service
});

1 个答案:

答案 0 :(得分:-1)

这使得worker和main两个线程都可以被监视,如果一个抛出异常,app就会退出,或者你可以抛出异常

工作线程有一个监视器线程,它可以处理异常并在不退出的情况下做一些合理的事情,或者在这种情况下它会重新抛出并将其发送回主线程,这将退出应用程序。

static void Main(string[] args)
{
    var tokenSource = new CancellationTokenSource();
    var token = tokenSource.Token;

    var worker = Task.Run(async () =>
    {
        try
        {
            var task = Task.Run(() => throw new Exception("hi"));
            await task;
        }
        catch (Exception e)
        {
            Console.WriteLine("Async...");
            throw;
        }

    }, token);

    var main = Task.Run(() =>
    {
        while (!token.IsCancellationRequested)
        {
            Thread.Sleep(1);
        }
    }, token);

    var tasks = new[] { worker, main };
    var index = Task.WaitAny(tasks);

    var taskThatStopped = tasks[index];
    if (taskThatStopped.IsFaulted)
    {
        Console.WriteLine("Task quit because of a fault");
        Console.WriteLine(taskThatStopped.Exception.InnerException.Message);
    }
    tokenSource.Cancel();
    try
    {
        Task.WaitAll(tasks);
    }
    catch (Exception e)
    {
    }
}