diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs index a6fe48e72..258f2e5c5 100755 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -229,7 +229,14 @@ namespace ArchiSteamFarm { CardsFarmer = new CardsFarmer(this); Trading = new Trading(this); - if ((AcceptConfirmationsTimer == null) && (BotConfig.AcceptConfirmationsPeriod > 0)) { + HeartBeatTimer = new Timer( + async e => await HeartBeat().ConfigureAwait(false), + null, + TimeSpan.FromMinutes(1) + TimeSpan.FromMinutes(0.2 * Bots.Count), // Delay + TimeSpan.FromMinutes(1) // Period + ); + + if (BotConfig.AcceptConfirmationsPeriod > 0) { AcceptConfirmationsTimer = new Timer( async e => await AcceptConfirmations(true).ConfigureAwait(false), null, @@ -238,16 +245,7 @@ namespace ArchiSteamFarm { ); } - if (HeartBeatTimer == null) { - HeartBeatTimer = new Timer( - async e => await HeartBeat().ConfigureAwait(false), - null, - TimeSpan.FromMinutes(1) + TimeSpan.FromMinutes(0.2 * Bots.Count), // Delay - TimeSpan.FromMinutes(1) // Period - ); - } - - if ((SendItemsTimer == null) && (BotConfig.SendTradePeriod > 0)) { + if (BotConfig.SendTradePeriod > 0) { SendItemsTimer = new Timer( async e => await ResponseLoot(BotConfig.SteamMasterID).ConfigureAwait(false), null, @@ -268,16 +266,19 @@ namespace ArchiSteamFarm { } public void Dispose() { + // Those are objects that are always being created if constructor doesn't throw exception + ArchiWebHandler.Dispose(); + CardsFarmer.Dispose(); GiftsSemaphore.Dispose(); + HeartBeatTimer.Dispose(); LoginSemaphore.Dispose(); HandledGifts.Dispose(); + OwnedPackageIDs.Dispose(); + Trading.Dispose(); + // Those are objects that might be null and the check should be in-place AcceptConfirmationsTimer?.Dispose(); - ArchiWebHandler?.Dispose(); - CardsFarmer?.Dispose(); - HeartBeatTimer?.Dispose(); SendItemsTimer?.Dispose(); - Trading?.Dispose(); } internal async Task AcceptConfirmations(bool accept, Steam.ConfirmationDetails.EType acceptedType = Steam.ConfirmationDetails.EType.Unknown, ulong acceptedSteamID = 0, HashSet acceptedTradeIDs = null) { diff --git a/ArchiSteamFarm/CardsFarmer.cs b/ArchiSteamFarm/CardsFarmer.cs index 7b70adbc1..b2e4bc8b9 100755 --- a/ArchiSteamFarm/CardsFarmer.cs +++ b/ArchiSteamFarm/CardsFarmer.cs @@ -88,7 +88,7 @@ namespace ArchiSteamFarm { private readonly ManualResetEventSlim FarmResetEvent = new ManualResetEventSlim(false); private readonly SemaphoreSlim FarmingSemaphore = new SemaphoreSlim(1); private readonly Bot Bot; - private readonly Timer Timer; + private readonly Timer IdleFarmingTimer; [JsonProperty] internal bool ManualMode { get; private set; } @@ -102,8 +102,8 @@ namespace ArchiSteamFarm { Bot = bot; - if ((Timer == null) && (Program.GlobalConfig.IdleFarmingPeriod > 0)) { - Timer = new Timer( + if (Program.GlobalConfig.IdleFarmingPeriod > 0) { + IdleFarmingTimer = new Timer( e => CheckGamesForFarming(), null, TimeSpan.FromHours(Program.GlobalConfig.IdleFarmingPeriod) + TimeSpan.FromMinutes(0.5 * Bot.Bots.Count), // Delay @@ -113,11 +113,14 @@ namespace ArchiSteamFarm { } public void Dispose() { + // Those are objects that are always being created if constructor doesn't throw exception CurrentGamesFarming.Dispose(); - FarmResetEvent.Dispose(); + GamesToFarm.Dispose(); FarmingSemaphore.Dispose(); + FarmResetEvent.Dispose(); - Timer?.Dispose(); + // Those are objects that might be null and the check should be in-place + IdleFarmingTimer?.Dispose(); } internal async Task SwitchToManualMode(bool manualMode) { diff --git a/ArchiSteamFarm/WCF.cs b/ArchiSteamFarm/WCF.cs index 73c7e7986..27b37013a 100644 --- a/ArchiSteamFarm/WCF.cs +++ b/ArchiSteamFarm/WCF.cs @@ -81,7 +81,7 @@ namespace ArchiSteamFarm { public string GetStatus() => Program.GlobalConfig.SteamOwnerID == 0 ? "{}" : Bot.GetAPIStatus(); public void Dispose() { - Client?.Close(); + StopClient(); StopServer(); } @@ -141,6 +141,18 @@ namespace ArchiSteamFarm { return Client.HandleCommand(input); } + + private void StopClient() { + if (Client == null) { + return; + } + + if (Client.State != CommunicationState.Closed) { + Client.Close(); + } + + Client = null; + } } internal sealed class Client : ClientBase {