使用void处理异步异常
问题描述:
我正在使用异步CTP编写IO沉重的控制台应用程序。但我遇到异常问题。使用void处理异步异常
public static void Main()
{
while (true) {
try{
myobj.DoSomething(null);
}
catch(Exception){}
Console.Write("done");
//...
}
}
//...
public async void DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
并执行以下操作:“完成”被写入到控制台,然后我得到的调试异常,然后我按继续我的程序中存在。
什么给?
答
当您致电DoSomething()
它基本上创建一个Task
在引擎盖下,并开始Task
。由于您有void
签名,因此没有Task
对象发回信号或您可能已被阻止,因此执行直接完成。与此同时,任务会抛出一个无人问津的异常,我怀疑这就是程序终止的原因。
我想你想的行为更像是这样的:
public static void Main()
{
while (true) {
var t = myobj.DoSomething(null);
t.Wait();
if(t.HasException) {
break;
}
}
Console.Write("done");
//...
}
}
//...
public async Task DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
这将在每个DoSomething
阻塞,直到它完成,并退出循环,如果DoSomething
扔。当然,那么你真的没有做任何异步。但是从伪代码,我不能完全知道你想异步发生什么。
主要外购:对异步方法使用void
意味着您无法获得异常,除非您使用异步方法。作为一个同步调用,它基本上只是安排工作,结果消失在以太网中。
答
如果你给你的控制台应用程序异步兼容的情况下(例如,AsyncContext
(docs,source)从我AsyncEx库),那么你就可以赶上传播完成了这方面的异常,甚至从async void
方法:
public static void Main()
{
try
{
AsyncContext.Run(() => myobj.DoSomething(null));
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
Console.Write("done");
}
public async void DoSomething(string p)
{
if (p==null) throw new InvalidOperationException();
else await SomeAsyncMethod();
}
+4
你已经恢复了原力平衡。谢谢! – 2014-04-23 17:36:32
我不能调用t.Wait(),因为它阻塞了主控制台线程,所以我不能输入任何东西,所以SomeAsyncMethod永远不会完成(对于我的用法见:http://*.com/questions/6145246/how-to-write-c-5-async) – TDaver 2011-06-08 20:14:54
但我想通了!我不会等待任务,将它们放入列表中,并且在每次IO操作(当它们可以抛出异常时)之后,我检查列表是否有任何任务出错! – TDaver 2011-06-08 20:56:58
是的,通常最好启动所有的任务,将它们收集到一个列表中,然后将其收集到一个TaskEx.WhenAll(listOfTasks).Wait()当你想收集所有的工作 – 2011-06-08 23:48:54