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(); } } }