From c18964ceef3eb3a306c1797e53c9523494d47189 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Mon, 26 Feb 2018 18:48:57 +0100 Subject: [PATCH] Greatly improve ASF background operations I hated that Forget() for quite a long time now, finally this code looks much better now. --- ArchiSteamFarm/ArchiWebHandler.cs | 8 +-- ArchiSteamFarm/Bot.cs | 71 ++++++++++++++++----------- ArchiSteamFarm/CardsFarmer.cs | 4 +- ArchiSteamFarm/IPC.cs | 4 +- ArchiSteamFarm/MobileAuthenticator.cs | 4 +- ArchiSteamFarm/Utilities.cs | 66 +++++++++++-------------- 6 files changed, 81 insertions(+), 76 deletions(-) diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index fce9f6a6a..646327612 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -478,10 +478,10 @@ namespace ArchiSteamFarm { if (Program.GlobalConfig.InventoryLimiterDelay == 0) { InventorySemaphore.Release(); } else { - Task.Run(async () => { + Utilities.InBackground(async () => { await Task.Delay(Program.GlobalConfig.InventoryLimiterDelay * 1000).ConfigureAwait(false); InventorySemaphore.Release(); - }).Forget(); + }); } } } @@ -941,10 +941,10 @@ namespace ArchiSteamFarm { if (Program.GlobalConfig.InventoryLimiterDelay == 0) { InventorySemaphore.Release(); } else { - Task.Run(async () => { + Utilities.InBackground(async () => { await Task.Delay(Program.GlobalConfig.InventoryLimiterDelay * 1000).ConfigureAwait(false); InventorySemaphore.Release(); - }).Forget(); + }); } } } diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index 15a7928ec..32e037128 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -1157,7 +1157,7 @@ namespace ArchiSteamFarm { } if (!skipShutdownEvent) { - Events.OnBotShutdown().Forget(); + Utilities.InBackground(Events.OnBotShutdown); } } @@ -1208,7 +1208,7 @@ namespace ArchiSteamFarm { await BotDatabase.AddGamesToRedeemInBackground(gamesToRedeemInBackground).ConfigureAwait(false); if (BotDatabase.HasGamesToRedeemInBackground && (GamesRedeemerInBackgroundTimer == null) && IsConnectedAndLoggedOn) { - RedeemGamesInBackground().Forget(); + Utilities.InBackground(RedeemGamesInBackground); } } @@ -1264,7 +1264,7 @@ namespace ArchiSteamFarm { Stop(); } else { // Stop() will most likely block due to fuckup, don't wait for it - Task.Run(() => Stop()).Forget(); + Utilities.InBackground(() => Stop()); } Bots.TryRemove(BotName, out _); @@ -1352,7 +1352,10 @@ namespace ArchiSteamFarm { } HeartBeatFailures = 0; - Statistics?.OnHeartBeat().Forget(); + + if (Statistics != null) { + Utilities.InBackground(Statistics.OnHeartBeat); + } } catch (Exception e) { ArchiLogger.LogGenericDebuggingException(e); @@ -1363,7 +1366,7 @@ namespace ArchiSteamFarm { if (++HeartBeatFailures >= (byte) Math.Ceiling(Program.GlobalConfig.ConnectionTimeout / 10.0)) { HeartBeatFailures = byte.MaxValue; ArchiLogger.LogGenericWarning(Strings.BotConnectionLost); - Connect(true).Forget(); + Utilities.InBackground(() => Connect(true)); } } } @@ -1505,7 +1508,7 @@ namespace ArchiSteamFarm { } // Start - Start().Forget(); + Utilities.InBackground(Start); } private static bool IsAllowedToExecuteCommands(ulong steamID) { @@ -1607,10 +1610,10 @@ namespace ArchiSteamFarm { } await GiftsSemaphore.WaitAsync().ConfigureAwait(false); - Task.Run(async () => { + Utilities.InBackground(async () => { await Task.Delay(Program.GlobalConfig.GiftsLimiterDelay * 1000).ConfigureAwait(false); GiftsSemaphore.Release(); - }).Forget(); + }); } private static async Task LimitLoginRequestsAsync() { @@ -1619,10 +1622,10 @@ namespace ArchiSteamFarm { } await LoginSemaphore.WaitAsync().ConfigureAwait(false); - Task.Run(async () => { + Utilities.InBackground(async () => { await Task.Delay(Program.GlobalConfig.LoginLimiterDelay * 1000).ConfigureAwait(false); LoginSemaphore.Release(); - }).Forget(); + }); } private void OnChatInvite(SteamFriends.ChatInviteCallback callback) { @@ -2097,7 +2100,7 @@ namespace ArchiSteamFarm { } if (BotDatabase.HasGamesToRedeemInBackground) { - RedeemGamesInBackground().Forget(); + Utilities.InBackground(RedeemGamesInBackground); } ArchiHandler.RequestItemAnnouncements(); @@ -2105,15 +2108,20 @@ namespace ArchiSteamFarm { // Sometimes Steam won't send us our own PersonaStateCallback, so request it explicitly RequestPersonaStateUpdate(); - ArchiWebHandler.HasValidApiKey().Forget(); // This will pre-cache API key for eventual further usage - InitializeFamilySharing().Forget(); - Statistics?.OnLoggedOn().Forget(); + // This will pre-cache API key for eventual further usage + Utilities.InBackground(ArchiWebHandler.HasValidApiKey); + + Utilities.InBackground(InitializeFamilySharing); + + if (Statistics != null) { + Utilities.InBackground(Statistics.OnLoggedOn); + } if (BotConfig.SteamMasterClanID != 0) { - Task.Run(async () => { + Utilities.InBackground(async () => { await ArchiWebHandler.JoinGroup(BotConfig.SteamMasterClanID).ConfigureAwait(false); JoinMasterChat(); - }).Forget(); + }); } if (!BotConfig.FarmOffline) { @@ -2239,7 +2247,10 @@ namespace ArchiSteamFarm { } AvatarHash = avatarHash; - Statistics?.OnPersonaState(callback.Name, avatarHash).Forget(); + + if (Statistics != null) { + Utilities.InBackground(() => Statistics.OnPersonaState(callback.Name, avatarHash)); + } } else if ((callback.FriendID == LibraryLockedBySteamID) && (callback.GameID == 0)) { LibraryLockedBySteamID = 0; await CheckOccupationStatus().ConfigureAwait(false); @@ -2305,10 +2316,10 @@ namespace ArchiSteamFarm { ItemsCount = notification.Value; if (newItems) { - CardsFarmer.OnNewItemsNotification().Forget(); + Utilities.InBackground(CardsFarmer.OnNewItemsNotification); if (BotConfig.DismissInventoryNotifications) { - ArchiWebHandler.MarkInventory().Forget(); + Utilities.InBackground(ArchiWebHandler.MarkInventory); } } @@ -2318,7 +2329,7 @@ namespace ArchiSteamFarm { TradesCount = notification.Value; if (newTrades) { - Trading.OnNewTrade().Forget(); + Utilities.InBackground(Trading.OnNewTrade); } break; @@ -3005,10 +3016,10 @@ namespace ArchiSteamFarm { } // Schedule the task after some time so user can receive response - Task.Run(async () => { + Utilities.InBackground(async () => { await Task.Delay(1000).ConfigureAwait(false); await Program.Exit().ConfigureAwait(false); - }).Forget(); + }); return FormatStaticResponse(Strings.Done); } @@ -3031,7 +3042,7 @@ namespace ArchiSteamFarm { await CardsFarmer.StopFarming().ConfigureAwait(false); } - CardsFarmer.StartFarming().Forget(); + Utilities.InBackground(CardsFarmer.StartFarming); return FormatBotResponse(Strings.Done); } @@ -3474,10 +3485,10 @@ namespace ArchiSteamFarm { } // Schedule the task after some time so user can receive response - Task.Run(async () => { + Utilities.InBackground(async () => { await Task.Delay(1000).ConfigureAwait(false); SteamFriends.LeaveChat(chatID); - }).Forget(); + }); return FormatBotResponse(Strings.Done); } @@ -4330,10 +4341,10 @@ namespace ArchiSteamFarm { } // Schedule the task after some time so user can receive response - Task.Run(async () => { + Utilities.InBackground(async () => { await Task.Delay(1000).ConfigureAwait(false); await Program.Restart().ConfigureAwait(false); - }).Forget(); + }); return FormatStaticResponse(Strings.Done); } @@ -4362,7 +4373,7 @@ namespace ArchiSteamFarm { } StopFamilySharingInactivityTimer(); - CardsFarmer.Resume(true).Forget(); + Utilities.InBackground(() => CardsFarmer.Resume(true)); return FormatBotResponse(Strings.BotAutomaticIdlingNowResumed); } @@ -4412,7 +4423,7 @@ namespace ArchiSteamFarm { } SkipFirstShutdown = true; - Start().Forget(); + Utilities.InBackground(Start); return FormatBotResponse(Strings.Done); } @@ -4934,7 +4945,7 @@ namespace ArchiSteamFarm { private async Task Start() { if (!KeepRunning) { KeepRunning = true; - Utilities.StartBackgroundAction(HandleCallbacks); + Utilities.InBackground(HandleCallbacks, true); ArchiLogger.LogGenericInfo(Strings.Starting); } diff --git a/ArchiSteamFarm/CardsFarmer.cs b/ArchiSteamFarm/CardsFarmer.cs index 5241d8aab..906b41dfb 100755 --- a/ArchiSteamFarm/CardsFarmer.cs +++ b/ArchiSteamFarm/CardsFarmer.cs @@ -101,7 +101,7 @@ namespace ArchiSteamFarm { return; } - StopFarming().Forget(); + Utilities.InBackground(StopFarming); } internal async Task OnNewGameAdded() { @@ -255,7 +255,7 @@ namespace ArchiSteamFarm { } KeepFarming = NowFarming = true; - Utilities.StartBackgroundFunction(Farm); + Utilities.InBackground(Farm, true); } finally { FarmingInitializationSemaphore.Release(); } diff --git a/ArchiSteamFarm/IPC.cs b/ArchiSteamFarm/IPC.cs index ae7546e5c..e29534007 100644 --- a/ArchiSteamFarm/IPC.cs +++ b/ArchiSteamFarm/IPC.cs @@ -119,7 +119,7 @@ namespace ArchiSteamFarm { } Logging.InitHistoryLogger(); - Utilities.StartBackgroundFunction(HandleRequests); + Utilities.InBackground(HandleRequests, true); ASF.ArchiLogger.LogGenericInfo(Strings.IPCReady); } @@ -802,7 +802,7 @@ namespace ArchiSteamFarm { return; } - Utilities.StartBackgroundFunction(() => HandleRequest(context), false); + Utilities.InBackground(() => HandleRequest(context)); } } catch (ObjectDisposedException e) { ASF.ArchiLogger.LogGenericDebuggingException(e); diff --git a/ArchiSteamFarm/MobileAuthenticator.cs b/ArchiSteamFarm/MobileAuthenticator.cs index 642fd0753..2c121f69b 100644 --- a/ArchiSteamFarm/MobileAuthenticator.cs +++ b/ArchiSteamFarm/MobileAuthenticator.cs @@ -199,10 +199,10 @@ namespace ArchiSteamFarm { if (Program.GlobalConfig.ConfirmationsLimiterDelay == 0) { ConfirmationsSemaphore.Release(); } else { - Task.Run(async () => { + Utilities.InBackground(async () => { await Task.Delay(Program.GlobalConfig.ConfirmationsLimiterDelay * 1000).ConfigureAwait(false); ConfirmationsSemaphore.Release(); - }).Forget(); + }); } } } diff --git a/ArchiSteamFarm/Utilities.cs b/ArchiSteamFarm/Utilities.cs index 72e9857df..738ac0292 100644 --- a/ArchiSteamFarm/Utilities.cs +++ b/ArchiSteamFarm/Utilities.cs @@ -21,11 +21,9 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Net; -using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using Humanizer; @@ -35,10 +33,6 @@ namespace ArchiSteamFarm { internal static class Utilities { private static readonly Random Random = new Random(); - [SuppressMessage("ReSharper", "UnusedParameter.Global")] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void Forget(this object obj) { } - internal static string GetArgsString(string[] args, byte argsToSkip, string delimiter = " ") { if ((args == null) || (args.Length < argsToSkip) || string.IsNullOrEmpty(delimiter)) { ASF.ArchiLogger.LogNullError(nameof(args) + " || " + nameof(delimiter)); @@ -80,6 +74,36 @@ namespace ArchiSteamFarm { internal static uint GetUnixTime() => (uint) DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + internal static void InBackground(Action action, bool longRunning = false) { + if (action == null) { + ASF.ArchiLogger.LogNullError(nameof(action)); + return; + } + + TaskCreationOptions options = TaskCreationOptions.DenyChildAttach; + + if (longRunning) { + options |= TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness; + } + + Task.Factory.StartNew(action, options); + } + + internal static void InBackground(Func function, bool longRunning = false) { + if (function == null) { + ASF.ArchiLogger.LogNullError(nameof(function)); + return; + } + + TaskCreationOptions options = TaskCreationOptions.DenyChildAttach; + + if (longRunning) { + options |= TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness; + } + + Task.Factory.StartNew(function, options); + } + internal static bool IsValidHexadecimalString(string text) { if (string.IsNullOrEmpty(text)) { ASF.ArchiLogger.LogNullError(nameof(text)); @@ -145,36 +169,6 @@ namespace ArchiSteamFarm { return result.ToString(); } - internal static void StartBackgroundAction(Action action, bool longRunning = true) { - if (action == null) { - ASF.ArchiLogger.LogNullError(nameof(action)); - return; - } - - TaskCreationOptions options = TaskCreationOptions.DenyChildAttach; - - if (longRunning) { - options |= TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness; - } - - Task.Factory.StartNew(action, options).Forget(); - } - - internal static void StartBackgroundFunction(Func function, bool longRunning = true) { - if (function == null) { - ASF.ArchiLogger.LogNullError(nameof(function)); - return; - } - - TaskCreationOptions options = TaskCreationOptions.DenyChildAttach; - - if (longRunning) { - options |= TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness; - } - - Task.Factory.StartNew(function, options).Forget(); - } - internal static IEnumerable ToEnumerable(this T item) { yield return item; }