Находясь в мире синхронизации, у меня есть функция TryExecute, чтобы обернуть логику try / catch / log для повторного использования, например:
TryExecute(() => SyncFunction());
private static void TryExecute(Action action)
{
try
{
action();
}
catch (Exception ex)
{
Log(ex);
throw;
}
}
Я не понимаю, как переписать ее в шаблон асинхронности / ожидания.
Как я понимаю, у меня есть пять допустимых способов переписать его в async / await (не обращайте внимания на любые другие Visual Studio с предупреждением).
Использование исходной синхронизации TryExecute()
с делегатом async:
(1) TryExecute(async () => await AsyncFunction());
Кажется, он больше не ждет, TryExecute()
проходит без ожидания AsyncFunction()
до конца.
Перезаписывает на новую синхронизацию TryExecuteTask()
возвращает Task, вызывает его с или безасинхронный делегат:
(2) await TryExecuteTask(() => AsyncFunction());
(3) await TryExecuteTask(async () => await AsyncFunction());
private static Task TryExecuteTask(Func<Task> asyncAction)
{
try
{
return asyncAction();
}
catch (Exception ex)
{
Log(ex);
throw;
}
}
Или переписать на новый асинхронный TryExecuteAsync()
, вызвать его с или без асинхронного делегата:
(4) await TryExecuteAsync(() => AsyncFunction());
(5) await TryExecuteAsync(async () => await AsyncFunction());
private async static Task TryExecuteAsync(Func<Task> asyncAction)
{
try
{
await asyncAction();
}
catch (Exception ex)
{
Log(ex);
throw;
}
}
Но если я выброшу Exception
изнутри AsyncFunction()
, то ни один из вышеперечисленных пяти способов не может поймать Exception
.Все остановлено с необработанным исключением.Работает только catch без делегата:
(0) try
{
await AsyncFunction();
}
catch (Exception ex)
{
Log(ex);
}
Это означает, что я не могу использовать любые формы TryExecute()
из (1) в (5) для повторного использования логики try / catch / log, я могу только повторятьtry / catch / log везде, как (0).
Весь мой код консоли выглядит следующим образом:
class Program
{
async static Task Main(string[] args)
{
// Original sync way
TryExecute(() => SyncFunction());
Console.WriteLine("0");
try
{
await AsyncFunction();
}
catch (Exception ex)
{
Log(ex);
}
////Console.WriteLine("1");
////TryExecute(async () => await AsyncFunction());
////Console.WriteLine("2");
////await TryExecuteTask(() => AsyncFunction());
////Console.WriteLine("3");
////await TryExecuteTask(async () => await AsyncFunction());
////Console.WriteLine("4");
////await TryExecuteAsync(() => AsyncFunction());
////Console.WriteLine("5");
////await TryExecuteAsync(async () => await AsyncFunction());
Console.WriteLine("Finished without unhandled exception.");
}
private static void SyncFunction()
{
Console.WriteLine("SyncFunction starting");
Thread.Sleep(500);
Console.WriteLine("SyncFunction starting");
throw new Exception();
}
private async static Task AsyncFunction()
{
Console.WriteLine("AsyncFunction starting");
await Task.Run(() =>
{
Console.WriteLine("Sleep starting");
Thread.Sleep(500);
Console.WriteLine("Sleep end");
throw new Exception();
});
Console.WriteLine("AsyncFunction end");
}
private static void TryExecute(Action action)
{
try
{
action();
}
catch (Exception ex)
{
Log(ex);
}
}
private static Task TryExecuteTask(Func<Task> asyncAction)
{
try
{
return asyncAction();
}
catch (Exception ex)
{
Log(ex);
throw;
}
}
private async static Task TryExecuteAsync(Func<Task> asyncAction)
{
try
{
await asyncAction();
}
catch (Exception ex)
{
Log(ex);
throw;
}
}
private static void Log(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Из-за необработанного исключения я могу закомментировать только все фрагменты, кроме одного в Main()
для проверки каждого случая.