[英]Async exception not caught
这是我与服务器通信的异步方法:
public static Task<bool> ValidateEmail(string email)
{
var url = ServerBase + Resources + Authorization + "check_existence";
var queryString = SerializationHelper.CreateQueryString(new Dictionary<object, object> {{"email", email}});
try
{
return
HttpHelper.PostAsync(url, queryString, null).ContinueWith(
json => SerializationHelper.DeserializeValidationResponse(json.Result));
} catch (Exception e)
{
return TaskErrorHelper.Error<bool>(e);
}
}
未捕获序列化服务器响应(来自DeserializeValidationResponse
方法)时引发的异常。 我究竟做错了什么?
UPD: TaskErrorHelper.Error
代码:
internal static Task<T> Error<T>(Exception e)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetException(e);
return tcs.Task;
}
未捕获序列化服务器响应(来自DeserializeValidationResponse方法)时引发的异常。 我究竟做错了什么?
你没做错什么 错误的是您认为异常处理程序与延续有关。 让我们暂时忽略继续,只考虑一下:
class C
{
object obj = null;
Action action;
void M()
{
N();
action();
}
void N()
{
try
{
action = ()=>{Console.WriteLine(obj.ToString());};
}
catch (Exception ex)
{
Console.WriteLine("caught!");
}
}
这是你的信念,捕捉处理器应该捕获由抛出的异常action()
只是因为action
恰巧是有一个处理一个堆栈帧上创建的?
异常不是这样工作的。
您的情况只是这个小程序的一个更复杂的版本。 直到异常处理程序消失很长时间之后,连续委托才运行。 哎呀,延续甚至可能不在同一线程上运行!
那么如何获得例外? 如果继续引发异常,那么它将被自动捕获,并且该异常将存储在任务中。 然后,您可以将其拉出任务。
或者,您可以重写您的程序以将处理程序的副本放置在延续中:
public static Task<bool> ValidateEmail(string email)
{
var url = ...
var queryString = ...
try {
return HttpHelper.PostAsync(url, queryString, null).ContinueWith(
json => { try { ... } catch(Exception) { ... } });
} catch( ...
或者,如果您在C#5中使用async-await
,您会得到一些喜悦:
public static async Task<bool> ValidateEmail(string email)
{
var url = ...
var queryString = ...
try
{
HttpResponseMessage json = await HttpHelper.PostAsync(url, queryString, null);
SerializationHelper.DeserializeValidationResponse(json.Result));
}
catch (Exception e)
{
return false;
}
return true;
}
现在,编译器将重写您的代码,以便它可以执行您想要的操作。 await
的好处是您不必编写任何疯狂的“继续”逻辑。 编译器为您完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.