簡體   English   中英

未捕獲異步異常

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM