using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace MinecraftClient
{
///
/// Holds an asynchronous task with return value
///
/// Type of the return value
public class TaskWithResult
{
private AutoResetEvent resultEvent = new AutoResetEvent(false);
private Func task;
private T result = default(T);
private Exception exception = null;
private bool taskRun = false;
private object taskRunLock = new object();
///
/// Create a new asynchronous task with return value
///
/// Delegate with return value
public TaskWithResult(Func task)
{
this.task = task;
}
///
/// Check whether the task has finished running
///
public bool HasRun
{
get
{
return taskRun;
}
}
///
/// Get the task result (return value of the inner delegate)
///
/// Thrown if the task is not finished yet
public T Result
{
get
{
if (taskRun)
{
return result;
}
else throw new InvalidOperationException("Attempting to retrieve the result of an unfinished task");
}
}
///
/// Get the exception thrown by the inner delegate, if any
///
public Exception Exception
{
get
{
return exception;
}
}
///
/// Execute the task in the current thread and set the property or to the returned value
///
public void ExecuteSynchronously()
{
// Make sur the task will not run twice
lock (taskRunLock)
{
if (taskRun)
{
throw new InvalidOperationException("Attempting to run a task twice");
}
}
// Run the task
try
{
result = task();
}
catch (Exception e)
{
exception = e;
}
// Mark task as complete and release wait event
lock (taskRunLock)
{
taskRun = true;
}
resultEvent.Set();
}
///
/// Wait until the task has run from another thread and get the returned value or exception thrown by the task
///
/// Task result once available
/// Any exception thrown by the task
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 != null)
throw exception;
return result;
}
}
}