异步exception未被捕获或被吞没

从未来更新: TL; DR用于捕获您必须await异步方法中的表达式, Task.WaitAllTask.WaitAll

我创建了一个有点复杂的异步方法,只运行其他异步方法。 您可以忽略大部分内容,因为只有行var mSpekTask …是有意义的,我也不关心逻辑,我只想知道我的exception去了哪里。 我的主要问题是ex.ToString()永远不会被击中,即使在mSpecTask内部确实发生了exception。

 public async Task LoadAsync(IEnumerable feed, int? customerId, IProgress mSpecProgress, Action 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 LoadMSpecAsync(IProgress prg, IEnumerable ids) { return this.LoadAsync(prg, ids, Selector.M, SPMS, x => x.Order); } 

这是LoadAsync的代码,等待db.ExecuteTVP(progress,spName,id,parameters)生成exception。

  private async Task<Dictionary> LoadAsync(IProgress progress, IEnumerable ids, Selector s, string spName, Func k, Func 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方法抛出exception时,该exception将放在返回的Task 。 它不是直接向调用者提出的。 这是设计的。

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

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

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

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