使用void进行异步异常处理
本文关键字:异步 异常处理 void 使用 | 更新日期: 2023-09-27 17:58:37
我正在使用Async CTP编写一个IO繁重的控制台应用程序。但我遇到了一些例外的问题。
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();
}
发生以下情况:"done"被写入控制台,然后我在调试器中得到异常,然后我按continue我的程序存在
什么东西?
如果您为控制台应用程序提供异步兼容上下文(例如,来自我的AsyncEx库的AsyncContext
(docs,source)),则您可以捕获超出该上下文的异常,甚至可以从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();
}
当您调用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
意味着你失去了获得异常的能力,除非你是await
在使用该异步方法。作为一个同步调用,它基本上只是安排工作,结果消失在以太中。