Асинхронное исключение не было поймано или проглочено
Обновление из будущего: 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() , вызывающим исключения, но это не так.