异步异常未被捕获或被吞没

时间:2013-03-04 13:35:53

标签: c# asynchronous task-parallel-library

从以后更新: 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的代码,等待db.ExecuteTVP(progress,spName,id,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];
  }

3 个答案:

答案 0 :(得分:8)

async方法抛出异常时,该异常将放在返回的Task上。它不是直接向调用者提出的。这是设计的。

因此,您必须awaitTask返回的LoadMSpecAsync或让您的mSpecCompletionHandler检查其Task参数的异常。它会出现在那里。

答案 1 :(得分:1)

您可以按如下方式处理未观察到的任务例外:

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

答案 2 :(得分:0)

我将为自己的问题添加答案,因为我发现了一些有用的信息。中间方法LoadMSpecAsync正在吞噬异常。为此不要发生它需要一点柚木。您需要在返回类型之前添加async关键字,在“return”之后添加“await”关键字。