From b15c3a8e46cbc8a1f99c59474c3bd624bdd2409e Mon Sep 17 00:00:00 2001 From: ReinforceZwei <39955851+ReinforceZwei@users.noreply.github.com> Date: Wed, 12 May 2021 22:31:06 +0800 Subject: [PATCH] Fix calling schedule task cause deadlock (#1586) --- MinecraftClient/McClient.cs | 35 ++++++++++++++++--- .../Protocol/Handlers/Protocol16.cs | 9 +++++ .../Protocol/Handlers/Protocol18.cs | 11 +++++- MinecraftClient/Protocol/IMinecraftCom.cs | 6 ++++ 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index f55b5c65..27ed6346 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -701,13 +701,38 @@ namespace MinecraftClient /// Task to run public object ScheduleTask(Delegate task) { - var taskAndResult = new TaskWithResult(task); - lock (threadTasksLock) + if (!InvokeRequired()) { - threadTasks.Enqueue(taskAndResult); + return task.DynamicInvoke(); + } + else + { + var taskAndResult = new TaskWithResult(task); + lock (threadTasksLock) + { + threadTasks.Enqueue(taskAndResult); + } + taskAndResult.Block(); + return taskAndResult.Result; + } + } + + /// + /// Check if calling thread is main thread or other thread + /// + /// True if calling thread is other thread + public bool InvokeRequired() + { + int callingThreadId = Thread.CurrentThread.ManagedThreadId; + if (handler != null) + { + return handler.GetNetReadThreadId() != callingThreadId; + } + else + { + // net read thread (main thread) not yet ready + return false; } - taskAndResult.Block(); - return taskAndResult.Result; } #region Management: Load/Unload ChatBots and Enable/Disable settings diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs index 1ce4730d..aaf5affd 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol16.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs @@ -201,6 +201,15 @@ namespace MinecraftClient.Protocol.Handlers netRead.Start(); } + /// + /// Get net read thread (main thread) ID + /// + /// Net read thread ID + public int GetNetReadThreadId() + { + return netRead != null ? netRead.ManagedThreadId : -1; + } + public void Dispose() { try diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index cb6081bb..99424d88 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -67,7 +67,7 @@ namespace MinecraftClient.Protocol.Handlers PacketTypePalette packetPalette; SocketWrapper socketWrapper; DataTypes dataTypes; - Thread netRead; + Thread netRead; // main thread ILogger log; public Protocol18Handler(TcpClient Client, int protocolVersion, IMinecraftComHandler handler, ForgeInfo forgeInfo) @@ -1112,6 +1112,15 @@ namespace MinecraftClient.Protocol.Handlers netRead.Start(); } + /// + /// Get net read thread (main thread) ID + /// + /// Net read thread ID + public int GetNetReadThreadId() + { + return netRead != null ? netRead.ManagedThreadId : -1; + } + /// /// Disconnect from the server, cancel network reading. /// diff --git a/MinecraftClient/Protocol/IMinecraftCom.cs b/MinecraftClient/Protocol/IMinecraftCom.cs index 4770a098..42d66fcd 100644 --- a/MinecraftClient/Protocol/IMinecraftCom.cs +++ b/MinecraftClient/Protocol/IMinecraftCom.cs @@ -235,5 +235,11 @@ namespace MinecraftClient.Protocol /// /// The slot of the trade, starts at 0. bool SelectTrade(int selectedSlot); + + /// + /// Get net read thread (main thread) ID + /// + /// Net read thread ID + int GetNetReadThreadId(); } }