当前一个Task执行出错的时候,如何获取状态,不再执行下一个Task?

cnwolfs 2011-09-07 12:54:51
当前一个Task执行出错的时候,如何获取状态,不再执行下一个Task?

例如throw new Exception("");抛出了一个异常,之后如何不去执行下一个Task?


CancellationTokenSource canceltoken = new CancellationTokenSource();

var task = new Task(() =>
{
try
{
for (int i = 0; i < 1000; i++)
{
if (canceltoken.Token.IsCancellationRequested)
{
Console.WriteLine("CancellationRequested!");
throw new OperationCanceledException(canceltoken.Token);
}
else
{
Console.WriteLine("i={0}", i);
Thread.Sleep(1 * 1000);
throw new Exception("1222");
}
}
}
catch (TaskCanceledException TCEx)
{
Console.WriteLine("TCEx:" + TCEx.Message);
}
catch (Exception Ex)
{
Console.WriteLine("Ex:" + Ex.Message);
}
}, canceltoken.Token);

var task1 = task.ContinueWith((preTask) =>
{
try
{
if ((preTask.IsCanceled == false) && (preTask.IsCompleted == true) && (preTask.IsFaulted == false))
{
}

for (int i = 0; i < 1000; i++)
{
if (canceltoken.Token.IsCancellationRequested)
{
Console.WriteLine("CancellationRequested_1!");
throw new OperationCanceledException(canceltoken.Token);
}
else
{
Console.WriteLine("1 i={0}", i);
Thread.Sleep(1 * 1000);
}
}
}
catch (TaskCanceledException TCEx)
{
Console.WriteLine("TCEx:" + TCEx.Message);
}
catch (Exception Ex)
{
Console.WriteLine("Ex:" + Ex.Message);
}
}, canceltoken.Token);

task.Start();

...全文
259 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
cnwolfs 2011-10-05
  • 打赏
  • 举报
回复
wknight_IT

正解。

之前我也尝试过这种写法,只是被IDE弹出来的异常给蒙蔽了。
多谢。


var task1 = Task.Factory.StartNew(() =>
{
byte[] mBT = new byte[1];

mBT[0] = 0x00;
mBT[1] = 0x01;

//throw new Exception("I'm bad, but not too bad!");
});

try
{
task1.Wait();
}
catch (AggregateException ae)
{
foreach (var a in ae.InnerExceptions)
{
Console.WriteLine(task1.IsFaulted); //这里将输出True,表示task1任务失败了
Console.WriteLine(a.Message);
}
}
Console.WriteLine("press any key to continue");
Console.Read();



输出:
True
索引超出了数组界限。
press any key to continue


cnwolfs 2011-10-05
  • 打赏
  • 举报
回复
当运行到throw new Exception("I'm bad, but not too bad!");的时候,VS会在这行中断运行,并显示错误消息,这是没关系的,按F5继续查看后续操作。

在实际运行中也不会出错吗?这个是很不理解的,所以加了try catch

cnwolfs 2011-09-18
  • 打赏
  • 举报
回复
感觉了解的人真不多
风骑士之怒 2011-09-18
  • 打赏
  • 举报
回复
MSDN原文:
任务基础结构会将内部异常包装在 AggregateException 实例中。 AggregateException 具有一个 InnerExceptions 属性,可枚举该属性来检查引发的所有原始异常,并单独处理(或不处理)每个异常。 即使只引发了一个异常,也仍会将该异常包装在 AggregateException 中。

简单处理内部异常的例子

var task1 = Task.Factory.StartNew(() =>
{
throw new Exception("I'm bad, but not too bad!");
});

try
{
task1.Wait();
}
catch (AggregateException ae)
{
foreach (var a in ae.InnerExceptions)
{
Console.WriteLine(task1.IsFaulted); //这里将输出True,表示task1任务失败了
Console.WriteLine(a.Message);
}
}
Console.Read();


输出:
True
I'm bad, but not too bad!


当运行到throw new Exception("I'm bad, but not too bad!");的时候,VS会在这行中断运行,并显示错误消息,这是没关系的,按F5继续查看后续操作。

MSDN原文:
当启用“仅我的代码”时,在某些情况下,Visual Studio 将在引发异常的行上中断运行,并显示错误消息“异常未由用户代码处理”。此错误是良性的。 按 F5 继续并查看在这些示例中演示的异常处理行为。 若要阻止 Visual Studio 在出现第一个错误时中断运行,只需在“工具”->“选项”->“调试”->“常规”下取消选中“仅我的代码”复选框即可。



刚刚我没注意这段文字,所以上述两个回复你大概看下就行。

你对于在Task任务内部使用异常捕捉是错误的,他本身就帮你做了这些操作了,而且封装到一个AggregateException 实例中。你这个做法也不叫错误,try catch放到Task内部后,其实是属于Task内部的一个内容,一个操作了,try catch内部不管有没有异常,对于Task来说,其内部已经完成所有操作,所以你获取到的IsFaulted都为false的。

你主要还是因为看见IDE报了那些良性异常弹窗后,才在Task内部加异常捕捉的吧,有点多余,反而使得Task获取不到异常并存储到AggregateException 实例
风骑士之怒 2011-09-18
  • 打赏
  • 举报
回复
然后你再写个导致异常的程序,如 数组索引超出范围的异常,编译,运行exe查看
风骑士之怒 2011-09-18
  • 打赏
  • 举报
回复

var task1 = Task.Factory.StartNew(() =>
{
for (int i = 0; i < 1000; i++)
{
MessageBox.Show(i.ToString());
Thread.Sleep(2000);
throw new Exception("I'm bad, but not too bad!");
}
}).ContinueWith((t) =>
{
MessageBox.Show("success");
}, TaskContinuationOptions.NotOnFaulted);


找个WINFORM,编译项目,运行exe看效果

http://msdn.microsoft.com/zh-cn/library/dd997415.aspx

你好像对于Task和异常的处理理解有点偏差,仅仅局限于控制台程序弹出了个异常窗体??
萧炎 2011-09-10
  • 打赏
  • 举报
回复
LZ 抛出异常后直接return撒
try
{}
catch(ExCEPTION EX)
{
MESSAGEBOX.show(ex.message);
return;
}
cnwolfs 2011-09-10
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 aaronnanqh 的回复:]
CancellationTokenSource canceltoken = new CancellationTokenSource();

var task = new Task(() =>
{
try
{
for (int i = 0; i < 1000; i++)
{
if (canceltoken.Token.IsCancellationReque……
[/Quote]

6楼,我遇到的问题是
if ((preTask.IsCanceled == false) && (preTask.IsCompleted == true) && (preTask.IsFaulted == false))
这个语句总是取不到被取消的状态。就是IsCanceled = false,IsCompleted = true,IsFaulted = false

另外,我提到的错误不是throw一个取消的异常出来,而是普通的一个Exception,程序总有异常嘛




cnwolfs 2011-09-10
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 sp1234 的回复:]
晕!

充其量你写


C# code

try
{
方法1();
方法2();
}
catch(Exception ex)
{
Console.WriteLine("{0}:{1}", ex.GetType().Name, ex.Message);
}

也就行了。为了花哨而编程,不是真正的编程。
[/Quote]

感觉你在SQL板块中回帖还算技术性,在C#怎么每次回帖都感觉很差。
另外,你怎么这么没有耐心?你年龄比我小多了,怎么对编程就这么没耐性了?老啦?

从你的回答,我认为你根本不了解Task,仔细了解下再说吧,可以参照6楼的帖,他还是比较了解的。



cnwolfs 2011-09-10
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 lmaohuanl 的回复:]
引用 9 楼 zyloveyrf 的回复:

LZ 抛出异常后直接return撒
try
{}
catch(ExCEPTION EX)
{
MESSAGEBOX.show(ex.message);
return;
}

我觉得这样可行的
[/Quote]

可以仔细学下Task,这绝对不可行。

LMAOhuaNL 2011-09-10
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 zyloveyrf 的回复:]

LZ 抛出异常后直接return撒
try
{}
catch(ExCEPTION EX)
{
MESSAGEBOX.show(ex.message);
return;
}
[/Quote]
我觉得这样可行的
bdmh 2011-09-07
  • 打赏
  • 举报
回复
catch中加一个标记,for循环中判断这个标记,如果出错了,就break
AaronNanQH 2011-09-07
  • 打赏
  • 举报
回复
CancellationTokenSource canceltoken = new CancellationTokenSource();

var task = new Task(() =>
{
try
{
for (int i = 0; i < 1000; i++)
{
if (canceltoken.Token.IsCancellationRequested)
{
Console.WriteLine("CancellationRequested!");
throw new OperationCanceledException(canceltoken.Token);
}
else
{
Console.WriteLine("i={0}", i);
Thread.Sleep(1 * 1000);
throw new Exception("1222");
}
}
}
catch (TaskCanceledException TCEx)
{
Console.WriteLine("TCEx:" + TCEx.Message);
}
catch (Exception Ex)
{
Console.WriteLine("Ex:" + Ex.Message);
}
}, canceltoken.Token);

var task1 = task.ContinueWith((preTask) =>
{
try
{
if ((preTask.IsCanceled == false) && (preTask.IsCompleted == true) && (preTask.IsFaulted == false))
{
}

for (int i = 0; i < 1000; i++)
{
if (canceltoken.Token.IsCancellationRequested)
{
Console.WriteLine("CancellationRequested_1!");
throw new OperationCanceledException(canceltoken.Token);
}
else
{
Console.WriteLine("1 i={0}", i);
Thread.Sleep(1 * 1000);
}
}
}
catch (TaskCanceledException TCEx)
{
Console.WriteLine("TCEx:" + TCEx.Message);
}
catch (Exception Ex)
{
Console.WriteLine("Ex:" + Ex.Message);
}
}, canceltoken.Token,TaskContinuationOptions.OnlyOnRanToCompletion,TaskScheduler.Current);

task.Start();
AaronNanQH 2011-09-07
  • 打赏
  • 举报
回复
设置 TaskContinuationOptions.NotOnRanToCompletion 前置任务完成则后续任务才运行
  • 打赏
  • 举报
回复
晕!

充其量你写

try
{
方法1();
方法2();
}
catch(Exception ex)
{
Console.WriteLine("{0}:{1}", ex.GetType().Name, ex.Message);
}

也就行了。为了花哨而编程,不是真正的编程。
ycproc 2011-09-07
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 bdmh 的回复:]

catch中加一个标记,for循环中判断这个标记,如果出错了,就break
[/Quote]

这个方法是最常见的

但是 直接显示 出标号 也行

一般别人都懂的!!!

cnwolfs 2011-09-07
  • 打赏
  • 举报
回复
这个方法感觉有点笨

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧