mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-11-10 07:04:27 +00:00
Fix deadlock in FarmMultiple()
Our Forget() tasks are in fact getting forgotten when given async method stumbles upon await call. We were executing async Farm() via Forget(), but it was entirely possible that we won't get opportunity to await anything if we follow FarmHours() path, making FarmingSemaphore signaled until we're done farming hours.
This commit is contained in:
parent
02f3a74dc9
commit
96a69f2157
5 changed files with 39 additions and 11 deletions
|
@ -1,4 +1,5 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeEditing/TypingAssist/SmartIndentOnEnter/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/Highlighting/IncludeWarningsInSwea/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AnnotateCanBeNullParameter/@EntryIndexedValue">SUGGESTION</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=AnnotateCanBeNullTypeMember/@EntryIndexedValue">SUGGESTION</s:String>
|
||||
|
|
|
@ -3603,7 +3603,7 @@ namespace ArchiSteamFarm {
|
|||
private async Task Start() {
|
||||
if (!KeepRunning) {
|
||||
KeepRunning = true;
|
||||
Task.Factory.StartNew(HandleCallbacks, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning).Forget();
|
||||
Utilities.StartBackgroundAction(HandleCallbacks);
|
||||
ArchiLogger.LogGenericInfo(Strings.Starting);
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,13 @@ namespace ArchiSteamFarm {
|
|||
IdleFarmingTimer?.Dispose();
|
||||
}
|
||||
|
||||
internal void OnDisconnected() => StopFarming().Forget();
|
||||
internal void OnDisconnected() {
|
||||
if (!NowFarming) {
|
||||
return;
|
||||
}
|
||||
|
||||
StopFarming().Forget();
|
||||
}
|
||||
|
||||
internal async Task OnNewGameAdded() {
|
||||
// We aim to have a maximum of 2 tasks, one already parsing, and one waiting in the queue
|
||||
|
@ -222,7 +228,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
KeepFarming = NowFarming = true;
|
||||
Farm().Forget(); // Farm() will end when we're done farming, so don't wait for it
|
||||
Utilities.StartBackgroundFunction(Farm);
|
||||
} finally {
|
||||
FarmingSemaphore.Release();
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
|
||||
KeepRunning = true;
|
||||
Utilities.StartBackgroundFunction(Run);
|
||||
Task.Factory.StartNew(Run, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning).Forget();
|
||||
|
||||
ASF.ArchiLogger.LogGenericInfo(Strings.IPCReady);
|
||||
|
|
|
@ -29,6 +29,7 @@ using System.Globalization;
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using Humanizer;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
|
@ -40,17 +41,18 @@ namespace ArchiSteamFarm {
|
|||
internal static void Forget(this object obj) { }
|
||||
|
||||
internal static string GetArgsAsString(this string[] args, byte argsToSkip = 1) {
|
||||
if (args.Length >= argsToSkip) {
|
||||
return string.Join(" ", args.GetArgs(argsToSkip));
|
||||
if ((args == null) || (args.Length < argsToSkip)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(args));
|
||||
return null;
|
||||
}
|
||||
|
||||
ASF.ArchiLogger.LogNullError(nameof(args));
|
||||
return null;
|
||||
string result = string.Join(" ", args.GetArgs(argsToSkip));
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static string GetCookieValue(this CookieContainer cookieContainer, string url, string name) {
|
||||
if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(name)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(url) + " || " + nameof(name));
|
||||
if ((cookieContainer == null) || string.IsNullOrEmpty(url) || string.IsNullOrEmpty(name)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(cookieContainer) + " || " + nameof(url) + " || " + nameof(name));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -93,14 +95,32 @@ namespace ArchiSteamFarm {
|
|||
}
|
||||
}
|
||||
|
||||
internal static IEnumerable<T> ToEnumerable<T>(this T item) {
|
||||
internal static void StartBackgroundAction(Action action) {
|
||||
if (action == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(action));
|
||||
return;
|
||||
}
|
||||
|
||||
Task.Factory.StartNew(action, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning).Forget();
|
||||
}
|
||||
|
||||
internal static void StartBackgroundFunction(Func<Task> function) {
|
||||
if (function == null) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(function));
|
||||
return;
|
||||
}
|
||||
|
||||
Task.Factory.StartNew(function, TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning).Forget();
|
||||
}
|
||||
|
||||
internal static IEnumerable<T> ToEnumerable<T>(this T item) where T : struct {
|
||||
yield return item;
|
||||
}
|
||||
|
||||
internal static string ToHumanReadable(this TimeSpan timeSpan) => timeSpan.Humanize(3);
|
||||
|
||||
private static string[] GetArgs(this string[] args, byte argsToSkip = 1) {
|
||||
if (args.Length < argsToSkip) {
|
||||
if ((args == null) || (args.Length < argsToSkip)) {
|
||||
ASF.ArchiLogger.LogNullError(nameof(args));
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue