Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何捕获任务中任务中引发的异常_C#_Multithreading_Exception_Task - Fatal编程技术网

C# 如何捕获任务中任务中引发的异常

C# 如何捕获任务中任务中引发的异常,c#,multithreading,exception,task,C#,Multithreading,Exception,Task,我需要帮助捕获C#中的异常。我有一个Windows服务,它的作用类似于其他模块的包装器,因此为了不拥有多个Windows服务,我启动了所有模块/代理,这就是我们在包装器Windows服务中对它们的调用方式。每个“代理”都在自己的任务中启动。我无法控制代理本身在做什么,因此它可以并且将不时是这样一个代理启动任务或线程,如果抛出异常,我无法捕获它。我尝试了不同的方法,但没有成功。所以,如果在生产中发生这样的异常,我的整个服务都会崩溃,所有代理都会崩溃,这是一场噩梦。我尝试用一个示例代码来简化它: p

我需要帮助捕获C#中的异常。我有一个Windows服务,它的作用类似于其他模块的包装器,因此为了不拥有多个Windows服务,我启动了所有模块/代理,这就是我们在包装器Windows服务中对它们的调用方式。每个“代理”都在自己的任务中启动。我无法控制代理本身在做什么,因此它可以并且将不时是这样一个代理启动任务或线程,如果抛出异常,我无法捕获它。我尝试了不同的方法,但没有成功。所以,如果在生产中发生这样的异常,我的整个服务都会崩溃,所有代理都会崩溃,这是一场噩梦。我尝试用一个示例代码来简化它:

public class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        AppDomain.CurrentDomain.UnhandledException += (o, e) =>
        {
            Console.WriteLine("CurrentDomain Unhandled Exception: {0}", e.ExceptionObject);
        };

        TaskScheduler.UnobservedTaskException += (s, e) =>
        {
            Console.WriteLine("TaskScheduler.UnobservedTaskException Unhandled Exception: {0}", e.Exception);
            e.SetObserved();
        };

        Task.Factory.StartNew(() =>
            {

                Task.Factory.StartNew(() => throw new Exception("I am a exception ! Catch me !"));

            }, TaskCreationOptions.LongRunning)
        .ContinueWith((t) =>
                t.Exception.InnerExceptions.ToList().ForEach(e => Console.WriteLine("Error executing task.{0}", e)),
            TaskContinuationOptions.OnlyOnFaulted);

        Console.WriteLine("If you read this, application is not crashed!");

        Console.ReadKey();

        Task.Factory.StartNew(() =>
        {
            throw new Exception("I am a exception ! Catch me !");
        });
    }
}
那么如何捕捉异常呢?它不会被我的任何处理程序获取


重要的是,我对代码的这一部分没有影响,这是我的“代理人”:

Task.Factory.StartNew(() => throw new Exception("I am a exception ! Catch me !"));
其他一切我都能改变

编辑: 不幸的是,提供的解决方案似乎对我不起作用。我仍然无法捕获发生的异常。当我展示我的原始代码时,它可能会变得更清晰:

 private async Task StartAgent(IAgent agent)
    {
        _logger.LogInfo("Agent starting with instanceId {0}", agent.GetInstanceGuid());
        if (agent == null)
        {
            throw new ArgumentNullException("agent");
        }

        try
        {
            Task task = await Task.Factory.StartNew(async () =>
            {
                agent.Start();
            }, TaskCreationOptions.LongRunning);
                
                await task.ContinueWith((t) =>
            {
                var aggException = t.Exception.Flatten();
                foreach (var exception in aggException.InnerExceptions)
                    _logger.LogError("Error executing agent task.{0}", exception, t.Id);

            }, TaskContinuationOptions.OnlyOnFaulted);
            
            _agents[agent.GetInstanceGuid()].Task = task;
            _agents[agent.GetInstanceGuid()].LastTaskStatus = task.Status;
        }
        catch (Exception e)
        {
            _logger.LogError("Exception in Agent Task.",e);
        }
    }
因此,agent.Start()是我在任务中调用的,我不知道内部发生了什么。代理可以创建任务,线程他想要的一切。Start()也是空的,我无法更改接口来等待它

[Task.Factory.StartNew]被包装在一个void方法中

那么,代码故意忽略所有异常。这种“开火并忘记”的问题恰恰在于它忽略了返回的任务。所有异常都放置在该任务上,然后忽略该任务

TaskScheduler.UnobservedTaskException
捕获它


UnobservedtaskeException
AppDomain。第一次机会例外
是您唯一的实际选择。这两种方法都不是特别好(即,它们是全局处理程序),但它们是您唯一的选择,因为您无法控制的代码会显式忽略异常。

感谢所有的答案。我现在找到了一个对我有效的简单解决方案。我所要做的就是在app.config的“runtime”部分添加这个标志

<legacyUnhandledExceptionPolicy enabled="1" />

就像这里描述的:


即使我能够捕捉到异常,我的服务仍然会在之后停止。

有帮助吗?听起来像是一个很好的例子,这能回答你的问题吗?简短的回答是
waitandunwapexception
“重要的是我对这部分代码没有影响”你至少可以从这个调用中得到返回的
Task
Task.Factory.StartNew(()=>抛出新异常(“我是异常!抓住我!”)
或者这实际上是在某些客户机void方法中包装的?@MongZhu是的,它是在void方法中包装的。请参阅我的原始帖子上的编辑。谢谢你的帮助。