簡體   English   中英

異步異常未被捕獲或被吞噬

[英]Async exception not being caught or being swallowed

更新來自未來:TL; DR在您需要異步方法捕捉表情awaitTask.WaitAll ,或.Result

我創建了一個有點復雜的異步方法,它只運行其他異步方法。 您可以忽略其中的大部分內容,因為只有 var mSpekTask... 行很有趣,而且,我不關心邏輯,我只想知道我的異常去了哪里。 我的主要問題是 ex.ToString() 永遠不會被命中,即使在 mSpecTask 內部肯定會發生異常。

public async Task LoadAsync(IEnumerable<ProductRequest> feed, int? customerId,
    IProgress<int> mSpecProgress, Action<Task> mSpecCompletionHandler)
{
    var ids = feed.Select(x => x.ProductId.ToString()).Distinct().ToList();

    try
    {
        var mSpecTask = this.LoadMSpecAsync(mSpecProgress, ids);
    }
    catch (Exception ex)
    {
        ex.ToString();
    }
}

這是 LoadMSpecAsync 的代碼

public Task<ResultSet> LoadMSpecAsync(IProgress<int> prg, IEnumerable<string> ids)
{
    return this.LoadAsync(prg, ids, Selector.M, SPMS, x => x.Order);
}

這里是LoadAsync的代碼,await db.ExecuteTVP(progress, spName, ids, parameters) 產生異常。

private async Task<Dictionary<Pair, dynamic>> LoadAsync(IProgress<int> progress,
    IEnumerable<string> ids, Selector s, string spName, Func<dynamic, int> k,
    Func<dynamic, dynamic> f = null, object parameters = null)
{
    parameters = new ExpandoObject().CopyFromSafe(parameters);
    if (spName != SPMAP) ((dynamic)parameters).lang = this.languageCode;

    using (var db = new SqlConnection(this.connectionString))
    {
    await db.OpenAsync();

    var results = await db.ExecuteTVP(progress, spName, ids, parameters);

    db.Close();
    }

    return this.data[s];
}

async方法拋出異常時,該異常被放置在返回的Task 它不會直接向調用者提出。 這是設計使然。

因此,您必須awaitLoadMSpecAsync返回的Task或讓您的mSpecCompletionHandler檢查其Task參數是否存在異常。 它會出現在那里。

您可以按如下方式處理未觀察到的 Task 異常:

TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs eventArgs) =>
{
      eventArgs.SetObserved();
      ((AggregateException)eventArgs.Exception).Handle(ex =>
      {
          //TODO: inspect type and handle exception
          return true;
      });
};

我要為我自己的問題添加一個答案,因為我發現了一條有用的信息。 中間方法 LoadMSpecAsync 正在吞噬異常。 為了不發生這種情況,它需要一點柚木。 您需要在返回類型之前添加 async 關鍵字,在“return”之后添加“await”關鍵字。

我有一個異常被myTask.Wait() (或 WaitAsync)吞下,但這是一個任務嵌套問題。 也就是說,當我執行myTask.Wait() 時myTask有一個傳入參數 Task ,它也稱為myParameterTask.Wait() 參數 task有自己的Exception-catch 並且沒有throw ,所以最初拋出的 Exception 不會傳播回調用線程。

我認為myTask.Wait()拋出異常有問題,但事實並非如此。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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