JD2022-TU1/main/tools/lib/AbstractPlugin/QueryResult.cs

95 lines
No EOL
2.6 KiB
C#

using System;
using System.Threading;
namespace Plugin
{
/// <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 interface IQueryResult<T>
{
/// <summary>
/// Waits for the result, returns true if the timeout didn't expire.
/// </summary>
bool Join(out T result, int millisecondsTimeout = QueryResult<T>.DefaultTimeout);
/// <summary>
/// Triggered when the query is filled.
/// </summary>
event Action<T> Done;
}
/// <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>
{
public const int DefaultTimeout = 2500;
private readonly AbstractPlugin _plugin;
private readonly ManualResetEvent _waitHandle = new ManualResetEvent(false);
private T _content;
public QueryResult(AbstractPlugin plugin)
{
_plugin = plugin;
}
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;
_plugin.ReportTimeoutFailure();
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;
if (done != null)
{
done(Content);
}
}
}
}