任务<;T>;以及C#中的TaskContinuationOptions说明?
我有一个简单的代码:任务<;T>;以及C#中的TaskContinuationOptions说明?,c#,.net,multithreading,.net-4.0,task-parallel-library,C#,.net,Multithreading,.net 4.0,Task Parallel Library,我有一个简单的代码: var g= Task.Factory.StartNew<int> (() => 8) .ContinueWith (ant =>{throw null;}) .ContinueWith (a =>{ Console.WriteLine("OK");},TaskContinuationOptions.NotOnFaulted); try{ Console.WriteLine("1");
var g= Task.Factory.StartNew<int> (() => 8)
.ContinueWith (ant =>{throw null;})
.ContinueWith (a =>{ Console.WriteLine("OK");},TaskContinuationOptions.NotOnFaulted);
try{
Console.WriteLine("1");
g.Wait();
Console.WriteLine("2");
}
catch (AggregateException ex)
{Console.WriteLine("catch"); }
msdn:
TaskContinuationOptions.NotUnfault
指定如果继续任务的
antecedent引发了未处理的异常。此选项对无效
多任务连续性
嗯
这是正常的-不显示这一行导致上一行抛出异常
问题:
- 我是否因为没有检查
属性而获得异常
异常聚合异常
- 我必须始终检查先行项是否抛出异常(在每行中)?(我不能检查每一行!它没有任何意义,非常烦人)
块不应该包含异常吗?(我认为所有的异常都会出现在等待方法中……所以呢?)try-catch
aggregateeexception
异常
异常
属性
不,您会得到一个异常,因为任务g
由TPL取消(因为,如msdn所述,如果Antescedent任务引发异常,则不会计划此任务)
我们有3项任务:
catch (AggregateException ex)
{
Console.WriteLine("catch");
// Will print: Status in catch: Canceled
Console.WriteLine("Status in catch: {0}", g.Status);
}
我必须始终检查先行项是否抛出异常(在每个
行吗?(我不能检查每一行!它没有任何意义,而且
(非常烦人)
是,您应该观察先行任务异常以避免此问题:
static class TaskEx
{
public static Task ObserverExceptions(this Task task)
{
task.ContinueWith(t => { var ignore = t.Exception; },
TaskContinuationOptions.OnlyOnFaulted);
return task;
}
}
然后按如下方式使用:
var g= Task.Factory.StartNew<int> (() => 8)
.ContinueWith (ant =>{throw null;})
.ObserveExceptions()
.ContinueWith (a =>{ Console.WriteLine("OK");});
try{
Console.WriteLine("1");
g.Wait();
Console.WriteLine("2");
}
catch (AggregateException ex)
{Console.WriteLine("catch"); }
下面是一个扩展方法:
static class TaskEx
{
public static Task TransformWith(this Task future, Action<Task> continuation)
{
var tcs = new TaskCompletionSource<object>();
future
.ContinueWith(t =>
{
if (t.IsCanceled)
{
tcs.SetCanceled();
}
else if (t.IsFaulted)
{
tcs.SetException(t.Exception.InnerExceptions);
}
else
{
try
{
continuation(future);
tcs.SetResult(null);
}
catch (Exception e)
{
tcs.SetException(e);
}
}
}, TaskContinuationOptions.ExecuteSynchronously);
return tcs.Task;
}
}
静态类TaskEx
{
公共静态任务转换(此任务未来,操作继续)
{
var tcs=new TaskCompletionSource();
未来
.ContinueWith(t=>
{
如果(t.IsCanceled)
{
setCancelled();
}
否则,如果(t.IsFaulted)
{
SetException(t.Exception.innerException);
}
其他的
{
尝试
{
延续(未来);
tcs.SetResult(空);
}
捕获(例外e)
{
tcs.SetException(e);
}
}
},TaskContinuationOptions。同步执行);
返回tcs.Task;
}
}
- 我是否因为没有检查而获得AggregateException异常 异常属性
var myTask = Task.Factory.StartNew(() => { throw new NotImplementedException(); });
var myException = myTask.Exception.Flatten().InnerException as NotImplementedException;
- 我必须始终检查先行项是否抛出异常(在每个 行吗?(我不能检查每一行!它没有任何意义,而且 (非常烦人)
TaskContinuationOptions。OnlyOnFaulted
和TaskContinuationOptions。OnlyOnRanToCompletion
。
如果需要的话,您甚至应该创建第三个续集来处理取消
- try-catch块不应该吞下异常吗?(一) 认为所有异常都会出现在等待方法中……那么呢?)
TaskContinuationOptions。仅在任务继续上使用onfaulted
,以检查是否存在异常。只有在.net 4中关键字不可用的情况下,才能在调用方级别获取任务异常
处理聚合异常,如下所示:
catch(AggregateException aex)
{
aex.Handle(ex =>
{
// Do some handling and logging
return true;
}
}
唉,这个话题并不罕见。我在我的自定义
TaskEx
类中使用了几种扩展方法来解决这个问题。顺便说一句,你可以看看Joe Albahari关于这个主题的伟大文章:对于这类问题有一个很好的描述。我的意思是,不幸的是,这不是一个罕见的主题。我不知道,因为如果你从这里举一个例子,乔也给了你解决方案,并清楚地描述了这种行为。@SergeyTeplyakov不,他没有。他谈到检查异常属性(如果您不检查,您将得到异常),但他没有谈到以流畅的方式检查异常。他创建了task1和task2。这与我的示例不同。Sergey,关于您的上一个代码:如果我只使用有故障的
——我的应用程序不会死(对吗?),因为异常
属性已被检查。因此,我可以抛出myNewException
,它将被缓存在catch
子句中(我的应用程序仍然不会死)对吗?如果您在最后一个连续中只添加了一个Faulted,您仍然会得到AggregateException,因为g会将其状态更改为Cancelled。@RoyiNamir:我更改了澄清:“另一个问题是您有临时任务(我列表中的任务2),但您从未观察到。因为您从未观察到它的错误状态,所以它将抛出终结器来告诉您。否。一旦您允许异常(var ignore=t.exception;
)yo
var myTask = Task.Factory.StartNew(() => { throw new NotImplementedException(); });
var myException = myTask.Exception.Flatten().InnerException as NotImplementedException;
catch(AggregateException aex)
{
aex.Handle(ex =>
{
// Do some handling and logging
return true;
}
}