using System;
using System.Threading;
using JD.Interfaces.Remoting;
namespace JD.Remoting
{
///
/// Result of a query to the engine. Allows to wait until the result is available.
///
/// Type of data inside the result.
public class QueryResult : IQueryResult, IDisposable
{
public const int DefaultTimeout = 2500;
private readonly ManualResetEvent _waitHandle = new ManualResetEvent(false);
private readonly Action _reportTimeoutFailure;
private T _content;
public QueryResult(Action reportTimeoutFailure = null)
{
_reportTimeoutFailure = reportTimeoutFailure;
}
public T Content
{
get { return _content; }
set
{
_content = value;
_waitHandle.Set();
OnDone();
}
}
public bool Join(out T result, int millisecondsTimeout = DefaultTimeout)
{
if (_waitHandle.WaitOne(millisecondsTimeout))
{
result = _content;
return true;
}
result = _content;
_reportTimeoutFailure?.Invoke();
return false;
}
///
/// Separated in a backend and the interface so we can trigger the event right away if already filled.
///
private event Action DoneBackend;
///
/// Triggered when the query is filled.
///
public event Action Done
{
add
{
DoneBackend += value;
// When already set, we trigger the event right now.
if (_waitHandle.WaitOne(0))
{
OnDone();
}
}
remove { DoneBackend -= value; }
}
protected virtual void OnDone()
{
var done = DoneBackend;
done?.Invoke(Content);
}
public void Dispose()
{
_waitHandle?.Dispose();
}
}
}