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