C# 未捕获异步异常

C# 未捕获异步异常,c#,asynchronous,C#,Asynchronous,以下是我与服务器通信的异步方法: public static Task<bool> ValidateEmail(string email) { var url = ServerBase + Resources + Authorization + "check_existence"; var queryString = SerializationHelper.CreateQueryString(new Dictionary<object,

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

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);
        }
    }
从反序列化ValidationResponse方法序列化服务器响应时引发的异常未被捕获。我做错了什么

你没有做错什么。错误的是您认为异常处理程序与延续有关。让我们暂时离开它,只考虑一下:

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处理程序应该捕获操作引发的异常,因为操作恰好是在具有处理程序的堆栈框架上创建的

例外情况并非如此

你的情况只是这个小程序的一个更复杂的版本。直到异常处理程序消失很久之后,延续委托才会运行。见鬼,延续甚至可能不会在同一个线程上运行

那么,如何获得异常呢?如果继续引发异常,则将自动捕获该异常,并将异常存储在任务中。然后可以将其从任务中拉出

或者,您可以重写程序,将处理程序的副本放入延续:

public static Task<bool> ValidateEmail(string email)
{
    var url = ...
    var queryString = ...
    try {
        return HttpHelper.PostAsync(url, queryString, null).ContinueWith(
        json => { try { ... } catch(Exception) { ... } });
    } catch( ...
现在,编译器会重写您的代码,使其符合您的要求。等待的好处是,你不必写任何疯狂的逻辑继续;编译器会帮你做这件事

从反序列化ValidationResponse方法序列化服务器响应时引发的异常未被捕获。我做错了什么

你没有做错什么。错误的是您认为异常处理程序与延续有关。让我们暂时离开它,只考虑一下:

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处理程序应该捕获操作引发的异常,因为操作恰好是在具有处理程序的堆栈框架上创建的

例外情况并非如此

你的情况只是这个小程序的一个更复杂的版本。直到异常处理程序消失很久之后,延续委托才会运行。见鬼,延续甚至可能不会在同一个线程上运行

那么,如何获得异常呢?如果继续引发异常,则将自动捕获该异常,并将异常存储在任务中。然后可以将其从任务中拉出

或者,您可以重写程序,将处理程序的副本放入延续:

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

现在,编译器会重写您的代码,使其符合您的要求。等待的好处是,你不必写任何疯狂的逻辑继续;编译器会为您执行此操作。

将处理程序放入continuation确实有帮助,但我想从catch子句返回TaskErrorHelper.Error,它返回Task。最终结果将是Task类型,这不是我想要的。我在更新中添加了TaskErrorHelper.Error代码。将处理程序放在continuation中确实有帮助,但我想从catch子句返回TaskErrorHelper.Error,它返回任务。最终结果将是Task类型,这不是我想要的。我在更新中添加了TaskErrorHelper。错误代码。