public static async Task <Result> StartAsync(IAcsStarter starter, StartProperties properties, IProgress <ProgressState> progress = null, CancellationToken cancellation = default(CancellationToken)) { if (_busy) { return(null); } _busy = true; if (OptionDebugMode) { progress?.Report(ProgressState.Waiting); await Task.Delay(500, cancellation); _busy = false; return(GetResult(DateTime.MinValue)); } RemoveResultJson(); IKeyboardListener listener = null; if (properties.SetKeyboardListener) { try { listener = KeyboardListenerFactory.Get(); listener.Subscribe(); } catch (Exception e) { AcToolsLogging.Write("Can’t set listener: " + e); } } var start = DateTime.Now; try { progress?.Report(ProgressState.Preparing); await Task.Run(() => properties.Set(), cancellation); if (cancellation.IsCancellationRequested || OptionRaceIniTestMode) { return(null); } progress?.Report(ProgressState.Launching); await starter.RunAsync(cancellation); if (cancellation.IsCancellationRequested) { return(null); } var process = await starter.WaitUntilGameAsync(cancellation); await Task.Run(() => properties.SetGame(process), cancellation); if (cancellation.IsCancellationRequested) { return(null); } progress?.Report(ProgressState.Waiting); await starter.WaitGameAsync(cancellation); if (cancellation.IsCancellationRequested) { return(null); } } finally { _busy = false; if (cancellation.IsCancellationRequested) { starter.CleanUp(); } else { progress?.Report(ProgressState.Finishing); await starter.CleanUpAsync(cancellation); } properties.RevertChanges(); listener?.Dispose(); } return(GetResult(start)); }