Implement schedule main thread task with return value (#1579)

* Implement schedule main thread task with return value

* Revert change of TestBot.cs
This commit is contained in:
ReinforceZwei 2021-05-12 12:20:13 +08:00 committed by GitHub
parent 073458f5f2
commit f848495243
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 39 deletions

View file

@ -72,7 +72,7 @@ namespace MinecraftClient
{
if (delayTasks[i].Tick())
{
Handler.ScheduleTask(delayTasks[i].Task);
delayTasks[i].Task.DynamicInvoke();
tasksToRemove.Add(i);
}
}
@ -1390,21 +1390,19 @@ namespace MinecraftClient
}
/// <summary>
/// Schedule a task to run on main thread
/// Schedule a task to run on main thread. Returned value cannot be retrieved
/// </summary>
/// <param name="task">Task to run</param>
/// <param name="delayTicks">Run the task after X ticks (1 tick delay = ~100ms). 0 for no delay</param>
/// <example>
/// // Delay ~10 seconds
/// ScheduleTask(delegate ()
/// ScheduleTaskDelayed(new Action(() =>
/// {
/// /** Your code here **/
/// Console.WriteLine("10 seconds has passed");
/// }, 100);
/// }), 100);
/// </example>
protected void ScheduleTask(Action task, int delayTicks = 0)
{
if (task != null)
protected void ScheduleTaskDelayed(Delegate task, int delayTicks = 0)
{
if (delayTicks <= 0)
{
@ -1419,6 +1417,15 @@ namespace MinecraftClient
}
}
}
/// <summary>
/// Schedule a task to run on main thread.
/// </summary>
/// <param name="task">Task to run</param>
/// <returns>Any value returned from the task</returns>
protected object ScheduleTask(Delegate task)
{
return Handler.ScheduleTask(task);
}
/// <summary>
@ -1468,16 +1475,16 @@ namespace MinecraftClient
private class DelayedTask
{
private Action task;
private Delegate task;
private int Counter;
public Action Task { get { return task; } }
public Delegate Task { get { return task; } }
public DelayedTask(Action task)
public DelayedTask(Delegate task)
: this(task, 0)
{ }
public DelayedTask(Action task, int delayTicks)
public DelayedTask(Delegate task, int delayTicks)
{
this.task = task;
Counter = delayTicks;
@ -1494,17 +1501,6 @@ namespace MinecraftClient
return true;
return false;
}
/// <summary>
/// Execute the task
/// </summary>
public void Execute()
{
if (task != null)
{
task();
}
}
}
}
}

View file

@ -32,7 +32,7 @@ namespace MinecraftClient
private Queue<string> chatQueue = new Queue<string>();
private static DateTime nextMessageSendTime = DateTime.MinValue;
private Action threadTasks;
private Queue<TaskWithResult> threadTasks = new Queue<TaskWithResult>();
private object threadTasksLock = new object();
private readonly List<ChatBot> bots = new List<ChatBot>();
@ -312,7 +312,7 @@ namespace MinecraftClient
while (client.Client.Connected)
{
string text = ConsoleIO.ReadLine();
ScheduleTask(delegate () { HandleCommandPromptText(text); });
ScheduleTask(new Action(() => { HandleCommandPromptText(text); }));
}
}
catch (IOException) { }
@ -641,12 +641,14 @@ namespace MinecraftClient
SendRespawnPacket();
}
if (threadTasks != null)
{
lock (threadTasksLock)
{
threadTasks();
threadTasks = null;
while (threadTasks.Count > 0)
{
var taskToRun = threadTasks.Dequeue();
taskToRun.Execute();
taskToRun.Release();
}
}
}
@ -697,12 +699,15 @@ namespace MinecraftClient
/// Schedule a task to run on the main thread
/// </summary>
/// <param name="task">Task to run</param>
public void ScheduleTask(Action task)
public object ScheduleTask(Delegate task)
{
var taskAndResult = new TaskWithResult(task);
lock (threadTasksLock)
{
threadTasks += task;
threadTasks.Enqueue(taskAndResult);
}
taskAndResult.Block();
return taskAndResult.Result;
}
#region Management: Load/Unload ChatBots and Enable/Disable settings

View file

@ -222,6 +222,7 @@
<Compile Include="Protocol\MicrosoftAuthentication.cs" />
<Compile Include="Protocol\ProxiedWebRequest.cs" />
<Compile Include="Protocol\ReplayHandler.cs" />
<Compile Include="TaskWithResult.cs" />
<Compile Include="Translations.cs" />
<Compile Include="Inventory\VillagerInfo.cs" />
<Compile Include="WinAPI\ConsoleIcon.cs" />

View file

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace MinecraftClient
{
public class TaskWithResult
{
private Delegate Task;
private AutoResetEvent ResultEvent = new AutoResetEvent(false);
public object Result;
public TaskWithResult(Delegate task)
{
Task = task;
}
/// <summary>
/// Execute the delegate and set the <see cref="Result"/> property to the returned value
/// </summary>
/// <returns>Value returned from delegate</returns>
public object Execute()
{
Result = Task.DynamicInvoke();
return Result;
}
/// <summary>
/// Block the program execution
/// </summary>
public void Block()
{
ResultEvent.WaitOne();
}
/// <summary>
/// Resume the program execution
/// </summary>
public void Release()
{
ResultEvent.Set();
}
}
}