В данном конкретном случае без разницы, потому что вы не используете await, а тот что Task - вообще не скомпилируется, и мейн не скомпилируется, вы бы хоть проверяли код перед вставкой в вопрос.
И оба показанных метода являются синхронными. Не async делает метод асинхронным, а await.
async void - это подход "запустил и забыл", то есть вы запускаете асинхронную операцию, которую потом никак не отслеживаете, и если там будет выброшено исключение, то оно в лучшем случае умрет вместе с операцией где-то в пуле потоков, в худшем - обрушит контекст синхронизации, а вы будете гадать, что же на самом деле случилось и как это исключение перехватить.
Поэтому только await и только Task.
static async Task Main(string[] args)
{
await SomeTaskMethod();
}
static async Task SomeTaskMethod()
{
await Task.Delay(100);
Console.WriteLine("Метод закончил работу.");
}
Уберите await из мейна и не увидите вывод в консоль. Непредсказуемое поведение кода - всегда плохо.
Если же надо "запустил и забыл" async void, то обязательно стоит обрабатывать исключения и учитывать, что метод закончит работу в неподконтрольное вам время. То есть приложение должно как минимум работать дольше, чем этот метод.
static void Main(string[] args)
{
SomeVoidMethod();
Console.ReadKey();
}
static async void SomeVoidMethod()
{
await Task.Delay(100);
Console.WriteLine("Метод закончил работу.");
}
Уберите Console.ReadKey() из мейна и не увидите вывод в консоль. Непредсказуемое поведение кода - ну вы поняли.
А теперь вот так
// ПЛОХОЙ КОД
static void Main(string[] args)
{
try
{
SomeVoidMethod();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
}
static async void SomeVoidMethod()
{
await Task.Delay(100);
throw new InvalidOperationException("Метод дал сбой.");
}
Этот метод обрушит вам приложение во время выполнения возможно важного кода. Вдруг мейн что-то пишет на диск, например, сохраняет данные пользователя. Для мейна все идет нормально, но исключение, вызванное в async void методе уронит все приложение, и даже если вы его завернете в try-catch, это не поможет. Попробуйте поймать исключение не меняя код самого метода - у вас ничего не получится. Кстати, если в этом примере void заменить на Task, то исключение провалится в бездну, и вы его не увидите вообще, оно просто будет не работать, а вы не будете об этом знать и долго-долго искать причину, в чем дело.
Поэтому перехватывать исключения в async void методах - обязательная процедура.
static void Main(string[] args)
{
SomeVoidMethod();
Console.ReadKey();
}
static async void SomeVoidMethod()
{
try
{
await Task.Delay(100);
throw new InvalidOperationException("Метод дал сбой.");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Если хочется ловить исключение снаружи метода, используйте async Task и await.
Что касается
запустить из синхронного метода асинхронный
то не пишите код в конструкторах классов, пишите его в асинхронных методах.
var helper = new HelperClass();
await helper.StartAsync();
И не придется запускать асинхронный метод из синхронного. А для обработчиков событий во всяких винформах есть async void, и как с ним работать - я показал выше.
Почитать:
async-voidвыкинуть исключение и посмотри, что будет (throw new Exception()). Посмотри так же видео https://youtu.be/lh8cT6qI-nA Должно помочь разобраться вообще в теме асинхронного программирования – Frehzy Jun 14 '22 at 14:38awaitполучайте результат. Хотите кинуть какую-то задачу и забыть о ней - сделайте всё равно возвращение Task из метода. Иначе может случится такой прикол: gc.collect пытается вызвать финалайз через 5, 10, 15, 20 или 30 минут и вытаскивает исключение из таски, приложение падает, а ты не понимаешь из-за чего упало – Frehzy Jun 14 '22 at 14:43