ContinueWith TaskContinuationOptions.OnlyOnFaulted似乎没有捕获从启动任务抛出的异常 [英] ContinueWith TaskContinuationOptions.OnlyOnFaulted does not seem to catch an exception thrown from a started task

查看:213
本文介绍了ContinueWith TaskContinuationOptions.OnlyOnFaulted似乎没有捕获从启动任务抛出的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用ContinueWith和OnlyOnFaulted捕获从任务方法抛出的异常,如下所示。但是,我尝试运行此代码时会收到一个未处理的异常。



我希望任务运行到完成,因为我已经处理了异常。但是Task.Wait()运行到AggregateException。

  var taskAction = new Action(()=> 
{
Thread.Sleep(1000) ;
Console.WriteLine(任务等待一秒);
throw(new Exception(throwing for example));
});
任务t = Task.Factory.StartNew(taskAction);
t.ContinueWith(x => Console.WriteLine(in on on Faulted继续执行代码。捕获的任务异常+ t.Exception),TaskContinuationOptions.OnlyOnFaulted);
Console.WriteLine(主线程等待4秒);
Thread.Sleep(4000);
Console.WriteLine(等待4秒完成...检查任务是否完成);
Console.WriteLine(任务状态:+ t.Status);
t.Wait();

如果我在下面的任务方法中处理异常,一切都将按照我的期望正常进行。任务运行到完成,异常被记录,并且Wait也成功。

  var taskAction = new Action(()=> 
{
try
{
Thread.Sleep(1000);
Console.WriteLine(任务等待一秒);
throw(new Exception(throwing for example));
}
catch(Exception ex)
{
Console.WriteLine(仅在Action catch块中捕获异常);
}
});
任务t = Task.Factory.StartNew(taskAction);
t.ContinueWith(x => Console.WriteLine(in on on Faulted继续执行代码。捕获的任务异常+ t.Exception),TaskContinuationOptions.OnlyOnFaulted);
Console.WriteLine(主线程等待4秒);
Thread.Sleep(4000);
Console.WriteLine(等待4秒完成...检查任务是否完成);
Console.WriteLine(任务状态:+ t.Status);
t.Wait();

我的问题是:我使用 OnlyOnFaulted 正确地处理任务方法本身的异常总是更好吗?即使任务运行到异常,我也希望主线程继续。另外,我想从任务方法记录该异常。



注意:在进一步(有或没有错误)之前,我必须等待任务方法完成。 / p>

总结(我的理解到目前为止)



如果处理任务异常即如果等待或等待捕获异常,那么该异常将被传播到继续任务onfaulted。
即使在任务方法中也可以捕获异常并消耗。

  try 
{
t.wait();
}
catch(异常e)
{
LogError(e);
}

在上述情况下,在LogError被调用之前,与主要任务的onfaulted相关联的继续任务

解决方案

首先,您没有使用 OnlyOnFaulted 正确当您在任务上使用 ContinueWith 时,您不会真正更改该任务,您将返回任务继续(在您的情况下,您忽略)



如果原始任务发生故障(即在其中抛出异常)将保持错误(所以调用 Wait()就会重新抛出异常)。但是,这个延续会在任务发生故障并处理异常之后运行。



这意味着在你的代码中你会处理异常,但你也是用等待()。正确的代码应该如下所示:

 任务originalTask​​ = Task.Run(()=> throw new Exception()) ; 
任务continuationTask = originalTask​​.ContinueWith(t => Console.WriteLine(t.Exception),TaskContinuationOptions.OnlyOnFaulted);
continuationTask.Wait()
//两个任务完成。没有例外重新抛出

现在,正如Yuval Itzchakov指出的那样,你可以随意处理异常,但是如果您正在使用 async-await 等待异步(如果可以)(您不能在 Main )中更好阻止使用 Wait()

  try 
{
等待originalTask​​;
}
catch(异常e)
{
//处理异常
}


I'm trying to catch an exception thrown from a task method using ContinueWith and OnlyOnFaulted like below. However I get an unhandled exception while I try to run this code.

I'd like the task to run to completion since I have handled the exception already. But Task.Wait() runs into AggregateException.

var taskAction = new Action(() =>
{
    Thread.Sleep(1000); 
    Console.WriteLine("Task Waited for a sec");
    throw (new Exception("throwing for example"));
});
Task t = Task.Factory.StartNew(taskAction);
t.ContinueWith(x => Console.WriteLine("In the on Faulted continue with code. Catched exception from the task."+  t.Exception), TaskContinuationOptions.OnlyOnFaulted);
Console.WriteLine("Main thread waiting for 4 sec");
Thread.Sleep(4000);
Console.WriteLine("Wait of 4 secs complete..checking if task is completed?");
Console.WriteLine("Task State: " + t.Status);
t.Wait();    

If I handle the exception in the task method like below, everything will go normal as I expect. Task Runs Into Completion, Exception gets logged and Wait succeeds also.

var taskAction = new Action(() =>
{
    try
    {
        Thread.Sleep(1000); 
        Console.WriteLine("Task Waited for a sec"); 
        throw (new Exception("throwing for example"));
    }
    catch (Exception ex)
    {
        Console.WriteLine("Catching the exception in the Action catch block only");
    }
});
Task t = Task.Factory.StartNew(taskAction);
t.ContinueWith(x=> Console.WriteLine("In the on Faulted continue with code. Catched exception from the task."+  t.Exception), TaskContinuationOptions.OnlyOnFaulted);
Console.WriteLine("Main thread waiting for 4 sec");
Thread.Sleep(4000);
Console.WriteLine("Wait of 4 secs complete..checking if task is completed?");
Console.WriteLine("Task State: " + t.Status);
t.Wait();    

My question is: Am I using the OnlyOnFaulted correctly or is it always better to handle the exception in the task method itself? I would like the main thread to continue even if task runs into exception. Also, I want to log that exception from task method.

Note: I have to wait for the task method to complete before going further (with or without errors).

To summarize(my understanding so far)

If exception from Task is handled i.e. if wait or await catches the exception then the exception would be propagated to continuedtask onfaulted. Exception can be caught even in the task method and consumed\handled.

try
{ 
   t.wait();
}
catch(Exception e)
{
   LogError(e);
}

In above case before LogError gets called, continued task associated with the main task's onfaulted gets executed.

解决方案

First of all, you aren't using OnlyOnFaulted correctly. When you use ContinueWith on a task you don't really change that task, you get back a task continuation (which in your case you disregard).

If the original task faulted (i.e. had an exception thrown inside it) it would stay faulted (so calling Wait() on it would always rethrow the exception). The continuation however would run after the task faulted and handle the exception.

That means that in your code you do handle the exception, but you're also rethrowing it with Wait(). The correct code should look like this:

Task originalTask = Task.Run(() => throw new Exception());
Task continuationTask = originalTask.ContinueWith(t => Console.WriteLine(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
continuationTask.Wait()
// Both tasks completed. No exception rethrown

Now, as Yuval Itzchakov pointed out, you can handle the exception wherever you want but it would better if you were utilizing async-await to wait asynchronously if you can (you can't in Main) instead of blocking with Wait():

try
{
    await originalTask;
}
catch (Exception e)
{
    // handle exception
}

这篇关于ContinueWith TaskContinuationOptions.OnlyOnFaulted似乎没有捕获从启动任务抛出的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆