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();
}
}