简体   繁体   English

未捕获异步异常

[英]Async exception not caught

Here's my async method for communicating with server: 这是我与服务器通信的异步方法:

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);
        }
    }

An exception thrown while serializing server response (from DeserializeValidationResponse method) isn't caught. 未捕获序列化服务器响应(来自DeserializeValidationResponse方法)时引发的异常。 What am I doing wrong? 我究竟做错了什么?

UPD: TaskErrorHelper.Error code: UPD: TaskErrorHelper.Error代码:

internal static Task<T> Error<T>(Exception e)
    {
        var tcs = new TaskCompletionSource<T>();
        tcs.SetException(e);
        return tcs.Task;
    }

An exception thrown while serializing server response (from DeserializeValidationResponse method) isn't caught. 未捕获序列化服务器响应(来自DeserializeValidationResponse方法)时引发的异常。 What am I doing wrong? 我究竟做错了什么?

You're not doing anything wrong. 你没做错什么 What's wrong is your belief that the exception handler has anything to do with the continuation. 错误的是您认为异常处理程序与延续有关。 Let's leave continuations out of it for a moment and just consider this: 让我们暂时忽略继续,只考虑一下:

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!");
     }
  }

Is it your belief that the catch handler ought to catch the exception thrown by action() just because action happened to be created on a stack frame that had a handler? 这是你的信念,捕捉处理器应该捕获由抛出的异常action()只是因为action恰巧是有一个处理一个堆栈帧上创建的?

That's not how exceptions work. 异常不是这样工作的。

Your situation is just a more complicated version of this little program. 您的情况只是这个小程序的一个更复杂的版本。 The continuation delegate isn't run until long after the exception handler is gone. 直到异常处理程序消失很长时间之后,连续委托才运行。 Heck, the continuation might not even be run on the same thread! 哎呀,延续甚至可能不在同一线程上运行!

So how do you get the exception? 那么如何获得例外? If the continuation throws an exception then it will be caught automatically and the exception will be stored in the task. 如果继续引发异常,那么它将被自动捕获,并且该异常将存储在任务中。 You can then pull it out of the task. 然后,您可以将其拉出任务。

Or, you could rewrite your program to put a copy of the handler in the continuation: 或者,您可以重写您的程序以将处理程序的副本放置在延续中:

public static Task<bool> ValidateEmail(string email)
{
    var url = ...
    var queryString = ...
    try {
        return HttpHelper.PostAsync(url, queryString, null).ContinueWith(
        json => { try { ... } catch(Exception) { ... } });
    } catch( ...

Or, if you use async-await in C# 5, you do get some joy: 或者,如果您在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;
}

Now the compiler rewrites your code so that it does what you want. 现在,编译器将重写您的代码,以便它可以执行您想要的操作。 The benefit of await is that you don't have to write any of this crazy "continue with" logic; await的好处是您不必编写任何疯狂的“继续”逻辑。 the compiler does it for you. 编译器为您完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM