From fb4cda513b78e906b94633e194b3eb8da04d96cc Mon Sep 17 00:00:00 2001 From: JustArchi Date: Wed, 1 Feb 2017 00:44:52 +0100 Subject: [PATCH] Don't wait for bot being stopped too long --- ArchiSteamFarm/ASF.cs | 12 ++++++------ ArchiSteamFarm/Bot.cs | 4 ++-- ArchiSteamFarm/Events.cs | 2 +- ArchiSteamFarm/Program.cs | 38 +++++++++++++++++++------------------- GUI/MainForm.cs | 2 +- GUI/Program.cs | 36 +++++++++++++++++++++++------------- 6 files changed, 52 insertions(+), 42 deletions(-) diff --git a/ArchiSteamFarm/ASF.cs b/ArchiSteamFarm/ASF.cs index 390e109ef..51d309ffc 100644 --- a/ArchiSteamFarm/ASF.cs +++ b/ArchiSteamFarm/ASF.cs @@ -330,7 +330,7 @@ namespace ArchiSteamFarm { CreateBot(botName).Forget(); } - private static void OnDeleted(object sender, FileSystemEventArgs e) { + private static async void OnDeleted(object sender, FileSystemEventArgs e) { if ((sender == null) || (e == null)) { ArchiLogger.LogNullError(nameof(sender) + " || " + nameof(e)); return; @@ -343,7 +343,7 @@ namespace ArchiSteamFarm { if (botName.Equals(SharedInfo.ASF)) { ArchiLogger.LogGenericError(Strings.ErrorGlobalConfigRemoved); - Program.Exit(1); + await Program.Exit(1).ConfigureAwait(false); return; } @@ -353,7 +353,7 @@ namespace ArchiSteamFarm { } } - private static void OnRenamed(object sender, RenamedEventArgs e) { + private static async void OnRenamed(object sender, RenamedEventArgs e) { if ((sender == null) || (e == null)) { ArchiLogger.LogNullError(nameof(sender) + " || " + nameof(e)); return; @@ -366,7 +366,7 @@ namespace ArchiSteamFarm { if (oldBotName.Equals(SharedInfo.ASF)) { ArchiLogger.LogGenericError(Strings.ErrorGlobalConfigRemoved); - Program.Exit(1); + await Program.Exit(1).ConfigureAwait(false); return; } @@ -387,11 +387,11 @@ namespace ArchiSteamFarm { if (Program.GlobalConfig.AutoRestart) { ArchiLogger.LogGenericInfo(Strings.Restarting); await Task.Delay(5000).ConfigureAwait(false); - Program.Restart(); + await Program.Restart().ConfigureAwait(false); } else { ArchiLogger.LogGenericInfo(Strings.Exiting); await Task.Delay(5000).ConfigureAwait(false); - Program.Exit(); + await Program.Exit().ConfigureAwait(false); } } diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index 279dc2b13..444498eac 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -1830,7 +1830,7 @@ namespace ArchiSteamFarm { // Schedule the task after some time so user can receive response Task.Run(async () => { await Task.Delay(1000).ConfigureAwait(false); - Program.Exit(); + await Program.Exit().ConfigureAwait(false); }).Forget(); return Environment.NewLine + Strings.Done; @@ -2515,7 +2515,7 @@ namespace ArchiSteamFarm { // Schedule the task after some time so user can receive response Task.Run(async () => { await Task.Delay(1000).ConfigureAwait(false); - Program.Restart(); + await Program.Restart().ConfigureAwait(false); }).Forget(); return Environment.NewLine + Strings.Done; diff --git a/ArchiSteamFarm/Events.cs b/ArchiSteamFarm/Events.cs index 25cd480f8..b7dc43bfe 100644 --- a/ArchiSteamFarm/Events.cs +++ b/ArchiSteamFarm/Events.cs @@ -36,7 +36,7 @@ namespace ArchiSteamFarm { ASF.ArchiLogger.LogGenericInfo(Strings.NoBotsAreRunning); await Task.Delay(5000).ConfigureAwait(false); - Program.Exit(); + await Program.Exit().ConfigureAwait(false); } internal static void OnPersonaState(Bot bot, SteamFriends.PersonaStateCallback callback) { } diff --git a/ArchiSteamFarm/Program.cs b/ArchiSteamFarm/Program.cs index c6fb5e992..9d23a386f 100644 --- a/ArchiSteamFarm/Program.cs +++ b/ArchiSteamFarm/Program.cs @@ -52,12 +52,12 @@ namespace ArchiSteamFarm { private static bool ShutdownSequenceInitialized; - internal static void Exit(byte exitCode = 0) { + internal static async Task Exit(byte exitCode = 0) { if (exitCode != 0) { ASF.ArchiLogger.LogGenericError(Strings.ErrorExitingWithNonZeroErrorCode); } - Shutdown(); + await Shutdown().ConfigureAwait(false); Environment.Exit(exitCode); } @@ -114,8 +114,8 @@ namespace ArchiSteamFarm { return !string.IsNullOrEmpty(result) ? result.Trim() : null; } - internal static void Restart() { - if (!InitShutdownSequence()) { + internal static async Task Restart() { + if (!await InitShutdownSequence().ConfigureAwait(false)) { return; } @@ -199,7 +199,7 @@ namespace ArchiSteamFarm { // If we ran ASF as a client, we're done by now if (Mode.HasFlag(EMode.Client) && !Mode.HasFlag(EMode.Server)) { - Exit(); + await Exit().ConfigureAwait(false); } await ASF.CheckForUpdate().ConfigureAwait(false); @@ -214,7 +214,7 @@ namespace ArchiSteamFarm { if (GlobalConfig == null) { ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorGlobalConfigNotLoaded, globalConfigFile)); await Task.Delay(5 * 1000).ConfigureAwait(false); - Exit(1); + await Exit(1).ConfigureAwait(false); return; } @@ -258,7 +258,7 @@ namespace ArchiSteamFarm { if (GlobalDatabase == null) { ASF.ArchiLogger.LogGenericError(string.Format(Strings.ErrorDatabaseInvalid, globalDatabaseFile)); await Task.Delay(5 * 1000).ConfigureAwait(false); - Exit(1); + await Exit(1).ConfigureAwait(false); return; } @@ -269,7 +269,7 @@ namespace ArchiSteamFarm { WebBrowser = new WebBrowser(ASF.ArchiLogger); } - private static bool InitShutdownSequence() { + private static async Task InitShutdownSequence() { if (ShutdownSequenceInitialized) { return false; } @@ -277,9 +277,9 @@ namespace ArchiSteamFarm { ShutdownSequenceInitialized = true; WCF.StopServer(); - foreach (Bot bot in Bot.Bots.Values) { - bot.Stop(); - } + + IEnumerable tasks = Bot.Bots.Values.Select(bot => Task.Run(() => bot.Stop())); + await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(10 * 1000)); return true; } @@ -293,7 +293,7 @@ namespace ArchiSteamFarm { ShutdownResetEvent.Wait(); // We got a signal to shutdown - Exit(); + Exit().Wait(); } else { // Service IsRunningAsService = true; @@ -371,32 +371,32 @@ namespace ArchiSteamFarm { } } - private static void Shutdown() { - if (!InitShutdownSequence()) { + private static async Task Shutdown() { + if (!await InitShutdownSequence().ConfigureAwait(false)) { return; } ShutdownResetEvent.Set(); } - private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) { + private static async void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) { if (args?.ExceptionObject == null) { ASF.ArchiLogger.LogNullError(nameof(args) + " || " + nameof(args.ExceptionObject)); return; } ASF.ArchiLogger.LogFatalException((Exception) args.ExceptionObject); - Exit(1); + await Exit(1).ConfigureAwait(false); } - private static void UnobservedTaskExceptionHandler(object sender, UnobservedTaskExceptionEventArgs args) { + private static async void UnobservedTaskExceptionHandler(object sender, UnobservedTaskExceptionEventArgs args) { if (args?.Exception == null) { ASF.ArchiLogger.LogNullError(nameof(args) + " || " + nameof(args.Exception)); return; } ASF.ArchiLogger.LogFatalException(args.Exception); - Exit(1); + await Exit(1).ConfigureAwait(false); } [Flags] @@ -422,7 +422,7 @@ namespace ArchiSteamFarm { Stop(); }); - protected override void OnStop() => Shutdown(); + protected override async void OnStop() => await Shutdown().ConfigureAwait(false); } } } \ No newline at end of file diff --git a/GUI/MainForm.cs b/GUI/MainForm.cs index 0a063eb7b..e83a4538f 100644 --- a/GUI/MainForm.cs +++ b/GUI/MainForm.cs @@ -59,7 +59,7 @@ namespace ArchiSteamFarm { BotStatusForm.BotForms[PreviouslySelectedBotName].Visible = true; } - private void MainForm_FormClosed(object sender, FormClosedEventArgs e) => Program.InitShutdownSequence(); + private async void MainForm_FormClosed(object sender, FormClosedEventArgs e) => await Program.InitShutdownSequence().ConfigureAwait(false); private async void MainForm_Load(object sender, EventArgs e) { Logging.InitFormLogger(); diff --git a/GUI/Program.cs b/GUI/Program.cs index 14f9b2803..fd5128717 100644 --- a/GUI/Program.cs +++ b/GUI/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -16,8 +17,10 @@ namespace ArchiSteamFarm { internal static GlobalDatabase GlobalDatabase { get; private set; } internal static WebBrowser WebBrowser { get; private set; } - internal static void Exit(int exitCode = 0) { - InitShutdownSequence(); + private static bool ShutdownSequenceInitialized; + + internal static async Task Exit(int exitCode = 0) { + await InitShutdownSequence().ConfigureAwait(false); Environment.Exit(exitCode); } @@ -25,14 +28,21 @@ namespace ArchiSteamFarm { return null; // TODO } - internal static void InitShutdownSequence() { - foreach (Bot bot in Bot.Bots.Values.Where(bot => bot.KeepRunning)) { - bot.Stop(); + internal static async Task InitShutdownSequence() { + if (ShutdownSequenceInitialized) { + return false; } + + ShutdownSequenceInitialized = true; + + IEnumerable tasks = Bot.Bots.Values.Select(bot => Task.Run(() => bot.Stop())); + await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(10 * 1000)); + + return true; } - internal static void Restart() { - InitShutdownSequence(); + internal static async Task Restart() { + await InitShutdownSequence().ConfigureAwait(false); try { Process.Start(Assembly.GetEntryAssembly().Location, string.Join(" ", Environment.GetCommandLineArgs().Skip(1))); @@ -43,7 +53,7 @@ namespace ArchiSteamFarm { Environment.Exit(0); } - private static void Init() { + private static async Task Init() { AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler; TaskScheduler.UnobservedTaskException += UnobservedTaskExceptionHandler; @@ -77,7 +87,7 @@ namespace ArchiSteamFarm { } } - InitServices(); + await InitServices().ConfigureAwait(false); // If debugging is on, we prepare debug directory prior to running if (GlobalConfig.Debug) { @@ -95,13 +105,13 @@ namespace ArchiSteamFarm { Logging.InitEnhancedLoggers(); } - private static void InitServices() { + private static async Task InitServices() { string globalConfigFile = Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalConfigFileName); GlobalConfig = GlobalConfig.Load(globalConfigFile); if (GlobalConfig == null) { ArchiLogger.LogGenericError("Global config could not be loaded, please make sure that " + globalConfigFile + " exists and is valid!"); - Exit(1); + await Exit(1).ConfigureAwait(false); } string globalDatabaseFile = Path.Combine(SharedInfo.ConfigDirectory, SharedInfo.GlobalDatabaseFileName); @@ -109,7 +119,7 @@ namespace ArchiSteamFarm { GlobalDatabase = GlobalDatabase.Load(globalDatabaseFile); if (GlobalDatabase == null) { ArchiLogger.LogGenericError("Global database could not be loaded, if issue persists, please remove " + globalDatabaseFile + " in order to recreate database!"); - Exit(1); + await Exit(1).ConfigureAwait(false); } ArchiWebHandler.Init(); @@ -123,7 +133,7 @@ namespace ArchiSteamFarm { /// [STAThread] private static void Main() { - Init(); + Init().Wait(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm());