mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Stage 1
This commit is contained in:
parent
1ca023be36
commit
3a4d8951d5
20 changed files with 1511 additions and 389 deletions
|
|
@ -1,20 +1,24 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MinecraftClient
|
||||
{
|
||||
internal interface IMainThreadTask
|
||||
{
|
||||
void ExecuteSynchronously();
|
||||
void Cancel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holds an asynchronous task with return value
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the return value</typeparam>
|
||||
public class TaskWithResult<T>
|
||||
public sealed class TaskWithResult<T> : IMainThreadTask
|
||||
{
|
||||
private readonly AutoResetEvent resultEvent = new(false);
|
||||
private readonly Func<T> task;
|
||||
private T? result = default;
|
||||
private Exception? exception = null;
|
||||
private bool taskRun = false;
|
||||
private readonly Lock taskRunLock = new();
|
||||
private readonly TaskCompletionSource<T> completionSource = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
private int taskState;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new asynchronous task with return value
|
||||
|
|
@ -28,13 +32,7 @@ namespace MinecraftClient
|
|||
/// <summary>
|
||||
/// Check whether the task has finished running
|
||||
/// </summary>
|
||||
public bool HasRun
|
||||
{
|
||||
get
|
||||
{
|
||||
return taskRun;
|
||||
}
|
||||
}
|
||||
public bool HasRun => completionSource.Task.IsCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// Get the task result (return value of the inner delegate)
|
||||
|
|
@ -44,10 +42,10 @@ namespace MinecraftClient
|
|||
{
|
||||
get
|
||||
{
|
||||
if (taskRun)
|
||||
return result!;
|
||||
else
|
||||
if (!completionSource.Task.IsCompleted)
|
||||
throw new InvalidOperationException("Attempting to retrieve the result of an unfinished task");
|
||||
|
||||
return completionSource.Task.GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -58,40 +56,39 @@ namespace MinecraftClient
|
|||
{
|
||||
get
|
||||
{
|
||||
return exception;
|
||||
return completionSource.Task.Exception?.InnerException;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<T> AsTask()
|
||||
{
|
||||
return completionSource.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the task in the current thread and set the <see cref="Result"/> property or <see cref=""/>to the returned value
|
||||
/// </summary>
|
||||
public void ExecuteSynchronously()
|
||||
{
|
||||
// Make sur the task will not run twice
|
||||
lock (taskRunLock)
|
||||
{
|
||||
if (taskRun)
|
||||
{
|
||||
throw new InvalidOperationException("Attempting to run a task twice");
|
||||
}
|
||||
}
|
||||
if (Interlocked.CompareExchange(ref taskState, 1, 0) != 0)
|
||||
throw new InvalidOperationException("Attempting to run a task twice");
|
||||
|
||||
// Run the task
|
||||
try
|
||||
{
|
||||
result = task();
|
||||
completionSource.TrySetResult(task());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
exception = e;
|
||||
completionSource.TrySetException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Mark task as complete and release wait event
|
||||
lock (taskRunLock)
|
||||
{
|
||||
taskRun = true;
|
||||
}
|
||||
resultEvent.Set();
|
||||
public void Cancel()
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref taskState, 1, 0) != 0)
|
||||
return;
|
||||
|
||||
completionSource.TrySetException(new OperationCanceledException("Main-thread task was canceled before execution."));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -101,22 +98,7 @@ namespace MinecraftClient
|
|||
/// <exception cref="System.Exception">Any exception thrown by the task</exception>
|
||||
public T WaitGetResult()
|
||||
{
|
||||
// Wait only if the result is not available yet
|
||||
bool mustWait = false;
|
||||
lock (taskRunLock)
|
||||
{
|
||||
mustWait = !taskRun;
|
||||
}
|
||||
if (mustWait)
|
||||
{
|
||||
resultEvent.WaitOne();
|
||||
}
|
||||
|
||||
// Receive exception from task
|
||||
if (exception is not null)
|
||||
throw exception;
|
||||
|
||||
return result!;
|
||||
return completionSource.Task.GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue