Асинхронное исключение не было поймано или проглочено

Обновление из будущего: TL; DR, чтобы поймать выражения в асинхронных методах, которые вы должны await, Task.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, id, параметры) генерирует исключение.

      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];
  }

4 ответа

Решение

Когда async метод выдает исключение, это исключение помещается в возвращаемое Task, Он не поднимается напрямую для звонящего. Это по замыслу.

Итак, вы должны либо await Task вернулся из LoadMSpecAsync или ваш mSpecCompletionHandler изучить его Task аргумент за исключения. Это появится там.

Вы можете обрабатывать ненаблюдаемые исключения задачи следующим образом:

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

Я собираюсь добавить ответ на свой вопрос, потому что есть полезная информация, которую я узнал. Промежуточный метод LoadMSpecAsync поглощает исключение. Чтобы этого не произошло, нужен маленький тик. Вам нужно добавить ключевое слово async перед типом возврата и ключевое слово "await" после "return".

У меня было исключение, проглоченное myTask.Wait() (или WaitAsync), но это была проблема вложенности задач. То есть, когда я выполнил myTask.Wait(), myTask имел переданный параметр Task , который ТАКЖЕ вызывал myParameterTask.Wait() . У задачи с параметрами был собственный Exception-catch и не было throw , поэтому исходное исключение Exception не распространялось обратно в вызывающий поток.

Я думал, что возникла проблема с myTask.Wait() , вызывающим исключения, но это не так.

Другие вопросы по тегам