Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.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#_Exception_Task - Fatal编程技术网

C# 任务未处理的异常

C# 任务未处理的异常,c#,exception,task,C#,Exception,Task,我试图了解在任务对象中抛出但从未处理过的异常的情况 MSDN上说: 如果您不等待传播异常的任务,或 它的Exception属性,根据 垃圾收集任务时的.NET异常策略 所以我不太明白这些异常是如何影响程序流的。我认为这些异常应该在垃圾收集后立即中断执行。但我不能设计这种行为。在下面的代码段中,不会显示抛出的异常 // Do something ... Task.Run (()=> {throw new Exception("Exception in the task!");}); // D

我试图了解在任务对象中抛出但从未处理过的异常的情况

MSDN上说:

如果您不等待传播异常的任务,或 它的Exception属性,根据 垃圾收集任务时的.NET异常策略

所以我不太明白这些异常是如何影响程序流的。我认为这些异常应该在垃圾收集后立即中断执行。但我不能设计这种行为。在下面的代码段中,不会显示抛出的异常

// Do something ...
Task.Run (()=> {throw new Exception("Exception in the task!");});
// Do something else

请说明如何处理未处理的任务异常以及它们如何影响程序流。

您描述的行为与.NET 4中的一样,但强制垃圾收集并实际观察该行为将是困难的。关于这个问题,下面的引文应该更加清楚:

任务跟踪是否已处理未处理的异常 “已观察”。在本上下文中,“已观察”表示代码已加入 以某种方式完成任务,以便至少让人意识到 例外。这可能是对任务调用Wait/WaitAll。信息技术 在任务完成后可能正在检查任务的异常属性 完整的。也可以使用任务的结果属性。 如果任务发现其异常已以某种方式被观察到, 生活是美好的。但是,如果删除了对任务的所有引用 (使任务可用于垃圾收集),以及 尚未观察到异常,任务知道其异常 永远不会被观察到。在这种情况下,任务将利用 终结,并使用辅助对象传播未处理的 终结器线程上出现异常。与所描述的行为一致 早些时候,终结器线程上的该异常将未经处理,并且 调用默认的未处理异常逻辑,该逻辑用于记录 发布并使进程崩溃

他还建议使用两种有用的扩展方法来处理“触发并忘记”任务中的异常:一种忽略异常,另一种立即使进程崩溃:

public static Task IgnoreExceptions(this Task task)
{
    task.ContinueWith(c => { var ignored = c.Exception; },
        TaskContinuationOptions.OnlyOnFaulted |
        TaskContinuationOptions.ExecuteSynchronously |
        TaskContinuationOptions.DetachedFromParent);
    return task;
}

public static Task FailFastOnException(this Task task)
{
    task.ContinueWith(c => Environment.FailFast(“Task faulted”, c.Exception),
        TaskContinuationOptions.OnlyOnFaulted |
        TaskContinuationOptions.ExecuteSynchronously |
        TaskContinuationOptions.DetachedFromParent);
    return task;
}
在.NET 4.5中默认行为已更改。再次引用(感谢mike z在评论中引起我的注意):

使开发人员更容易基于 任务.NET 4.5更改未观察到的任务的默认异常行为 例外情况。而未观察到的例外情况仍将导致 要引发的UnobservedTaskException事件(不这样做将是一个错误) 默认情况下,进程不会崩溃。而是 异常将在事件引发后被吃掉, 不管事件处理程序是否观察到异常。这 不过,可以配置行为


请注意上面的代码不太正确。您必须返回指向
任务的指针。继续执行
,而不是传入的任务:

public static Task IgnoreExceptions(this Task task)
{
    var t = task.ContinueWith(c => { var ignored = c.Exception; },
        TaskContinuationOptions.OnlyOnFaulted |
        TaskContinuationOptions.ExecuteSynchronously);
    return t;
}
编辑:

这很有挑战性,因为这取决于你如何将电话联系在一起。例如,以下调用的工作方式与我预期的不同:

public Task MyServiceCall()
{
  return Task.Run(() => DoSomething()).IgnoreExceptions();
}
此方法确实会引发异常,因为接受的答案返回初始任务(而不是观察异常的任务)。对于其他调用,例如
.Wait
.whalll
等,这可能会有问题。有人可能会认为任务永远不会抛出,但它可以抛出

但是,我建议的更改将破坏以下内容:

public void SomeMethod()
{
  var myTask = new Task(() => ...);
  myTask.IgnoreExceptions().Start();
}

在内部,我们已经决定淘汰这个扩展方法,因为它太混乱了

请看这里@SriramSakthivel谢谢,不是很详细,但很有帮助。@技术问题不是如何处理异常,而是未处理的异常如何影响程序流谢谢你的详细回答。虽然这对.NET 4是正确的,在.NET4.5中,该策略被更改为忽略未观察到的任务异常。@mikez感谢您提请我注意。我已经相应地编辑了答案。另外,根据“在RTM(.net 4.0)之前,默认值已被交换,因此DetachedFromParent现在是默认值,因此您可以从这些代码示例中删除DetachedFromParent,它们将按预期的方式运行。如果您确实希望附加任务,可以使用AttachedToParent。”