82 lines
No EOL
2.1 KiB
C#
82 lines
No EOL
2.1 KiB
C#
using System;
|
|
using System.Threading;
|
|
using JD.Interfaces.Remoting;
|
|
|
|
namespace JD.Remoting
|
|
{
|
|
/// <summary>
|
|
/// Result of a query to the engine. Allows to wait until the result is available.
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of data inside the result.</typeparam>
|
|
public class QueryResult<T> : IQueryResult<T>, 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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Separated in a backend and the interface so we can trigger the event right away if already filled.
|
|
/// </summary>
|
|
private event Action<T> DoneBackend;
|
|
|
|
/// <summary>
|
|
/// Triggered when the query is filled.
|
|
/// </summary>
|
|
public event Action<T> 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();
|
|
}
|
|
}
|
|
} |