未捕获异步异常 [英] Async exception not caught

查看:69
本文介绍了未捕获异步异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我与服务器通信的异步方法:

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

未捕获序列化服务器响应(从 DeserializeValidationResponse 方法)时引发的异常.我在做什么错了?

An exception thrown while serializing server response (from DeserializeValidationResponse method) isn't caught. What am I doing wrong?

UPD: TaskErrorHelper.Error 代码:

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

推荐答案

未捕获序列化服务器响应(来自DeserializeValidationResponse方法)时引发的异常.我在做什么错了?

An exception thrown while serializing server response (from DeserializeValidationResponse method) isn't caught. 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!");
     }
  }

您是否认为catch处理程序应该捕获 action()引发的异常,只是因为 action 恰巧是在具有处理程序的堆栈框架上创建的?

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?

这不是异常的工作方式.

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( ...

或者,如果您在C#5中使用 async-await ,您会得到一些快乐:

Or, if you use async-await in C# 5, you do get some joy:

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 的好处是您不必编写任何这种疯狂的继续"逻辑;编译器为您完成.

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; the compiler does it for you.

这篇关于未捕获异步异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆