.net 任务并行库和异常?
我应该这样做吗.net 任务并行库和异常?,.net,task-parallel-library,.net,Task Parallel Library,我应该这样做吗 int x = 0; Task<int> calc = Task.Factory.StartNew (() => 7 / x); try { Console.WriteLine (calc.Result); } catch (AggregateException aex) { Console.Write (aex.InnerException.Message); // Attempted to divide by 0 } intx=0; 任务计算=T
int x = 0;
Task<int> calc = Task.Factory.StartNew (() => 7 / x);
try
{
Console.WriteLine (calc.Result);
}
catch (AggregateException aex)
{
Console.Write (aex.InnerException.Message); // Attempted to divide by 0
}
intx=0;
任务计算=Task.Factory.StartNew(()=>7/x);
尝试
{
Console.WriteLine(计算结果);
}
捕获(聚合异常aex)
{
Console.Write(aex.InnerException.Message);//试图除以0
}
还是这个
int x = 0;
try
{
Task<int> calc = Task.Factory.StartNew (() => 7 / x);
Console.WriteLine (calc.Result);
}
catch (AggregateException aex)
{
Console.Write (aex.InnerException.Message); // Attempted to divide by 0
}
intx=0;
尝试
{
任务计算=Task.Factory.StartNew(()=>7/x);
Console.WriteLine(计算结果);
}
捕获(聚合异常aex)
{
Console.Write(aex.InnerException.Message);//试图除以0
}
如果任务在我们进入try-catch块之前立即启动,那么我们将无法捕获它 使用
任务
的一个要点是,你基本上不必担心这样的事情
正如您所注意到的,第一个示例中有两种可能的事件顺序:
StartNew()
是从线程A调用的Result
getter是从线程A调用的。任务尚未完成,因此调用被阻塞dividebyzeroception
结果
抛出聚合异常
StartNew()
是从线程A调用的dividebyzeroception
Result
getter是从线程A调用的。任务已经完成,因此调用会立即抛出aggregateeexception
Result
getter都会抛出异常,代码执行的顺序并不重要
只有当StartNew()
能够抛出aggregateeexception
时,您的第二个版本才有意义,但这永远不会发生
让我重复一遍:TPL负责所有的同步,您不必在这里担心。使用
任务的一个要点是,您基本上不必担心类似的事情
正如您所注意到的,第一个示例中有两种可能的事件顺序:
StartNew()
是从线程A调用的
Result
getter是从线程A调用的。任务尚未完成,因此调用被阻塞
委托在线程池线程B上执行,并抛出dividebyzeroception
线程A唤醒并结果
抛出聚合异常
第二种可能性是:
StartNew()
是从线程A调用的
委托在线程池线程B上执行,并抛出dividebyzeroception
Result
getter是从线程A调用的。任务已经完成,因此调用会立即抛出aggregateeexception
如您所见,在这两种情况下,Result
getter都会抛出异常,代码执行的顺序并不重要
只有当StartNew()
能够抛出aggregateeexception
时,您的第二个版本才有意义,但这永远不会发生
让我重复一遍:TPL负责所有的同步,您不必在这里担心它。任务有一个异常
属性,它保存在任务执行过程中抛出的异常(如果有)。这意味着您可以执行以下操作:
int x = 0;
Task<int> calc = Task.Factory.StartNew(() => 7 / x);
calc.ContinueWith(t => Console.WriteLine ("Got exception of {0}", t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
intx=0;
任务计算=Task.Factory.StartNew(()=>7/x);
calc.ContinueWith(t=>Console.WriteLine(“获取了{0}的异常”,t.exception),
TaskContinuationOptions.OnlyOnFaulted);
任务有一个异常
属性,该属性保存在任务执行期间引发的异常(如果有)。这意味着您可以执行以下操作:
int x = 0;
Task<int> calc = Task.Factory.StartNew(() => 7 / x);
calc.ContinueWith(t => Console.WriteLine ("Got exception of {0}", t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
intx=0;
任务计算=Task.Factory.StartNew(()=>7/x);
calc.ContinueWith(t=>Console.WriteLine(“获取了{0}的异常”,t.exception),
TaskContinuationOptions.OnlyOnFaulted);
您希望在try块中执行尽可能少的代码,因为包含的代码越多,您将捕获到的错误和不必要的异常就越多。你只想抓住那些你知道它们是良性的。你不想吞下虫子
因此,要么这样做:
var task = ...;
int result;
try { result = task.Result; } //just catch task.Result
...
甚至这个:
if (task.Exception != null) { /* error */ }
else { /* use task.Result */ }
您希望在try块中执行尽可能少的代码,因为包含的代码越多,您将捕获到的错误和不需要的异常就越多。你只想抓住那些你知道它们是良性的。你不想吞下虫子
因此,要么这样做:
var task = ...;
int result;
try { result = task.Result; } //just catch task.Result
...
甚至这个:
if (task.Exception != null) { /* error */ }
else { /* use task.Result */ }
在这种情况下,不需要将其包含在try块中。将不会引发异常,除非向其传递要执行的null操作。正在运行的操作引发的任何异常都将传播到任务中,而不是堆栈中
更一般地说,我认为这类情况的经验法则是,异常应该始终进入任务。例如,如果在异步方法中第一次等待之前抛出异常,它也会进入结果任务,而不是向上传播堆栈。在这种情况下,您不需要将其包括在try块中。将不会引发异常,除非向其传递要执行的null操作。正在运行的操作引发的任何异常都将传播到任务中,而不是堆栈中
更一般地说,我认为这类情况的经验法则是,异常应该始终进入任务。例如,如果在异步方法中第一次等待之前抛出异常,它也会进入结果任务,而不是向堆栈上传播。执行try{result=task.result;}
将阻止执行任务的线程,这可能不是他想要的。不确定他的意图。他的问题与那个问题是正交的,所以我忽略了它。我直截了当地回答他的问题。做try{result=