‘Async Void’ 사용은 일반적으로 아래의 이유를 들어 좋지 않은 것으로 간주한다1.
- You can’t wait for its completion (fire and forget)
- Any unhandled exceptions will terminate your process (can’t be caught)
- Difficult to test
C#에서 악명 높은 ‘Async Void’를 방지하는 좋은 방법으로 ‘ContinueWith’를 사용하는 것인데 아래의 소스는 SingletonSean(유튜브채널)의 ‘C# ASYNC/AWAIT’2 강좌에서 필요한 부분만 추출하여 전체 소스 형태로 편집한 것이다.
Program.cs
using System;
using System.Threading.Tasks;
namespace AsyncAwaitDemo
{
internal class Program
{
private static void Main()
{
var car = Car.CreateCarWithStartedEngine(OnEngineStarted);
Console.WriteLine(car.Status);
Console.ReadKey(true);
}
private static void OnEngineStarted(Task task)
{
if (task.Exception != null)
{
Console.WriteLine("Failed to start engine");
}
else
{
Console.WriteLine("Car.IsEngineStarted=" + Car.IsEngineStarted + ", Done.");
}
}
}
}
Car.cs (Model)
using System;
using System.Threading.Tasks;
namespace AsyncAwaitDemo
{
public class Car
{
public static bool IsEngineStarted { get; private set; }
private Car()
{
IsEngineStarted = false;
}
public static async Task<Car> CreateCarWithStartedEngine(Action<Task> onEngineStarted)
{
var car = new Car();
await StartEngine().ContinueWith(t => onEngineStarted?.Invoke(t));
return car;
}
private static async Task StartEngine()
{
Console.WriteLine("Starting engine.....");
for (var i = 0; i < 20; i++)
{
await Task.Delay(100);
Console.Write(".");
}
Console.WriteLine("");
await Task.Delay(100);
IsEngineStarted = true;
Console.WriteLine("Engine started!");
}
}
}