TellmePdmsPluging/Core/MainThreadInvoker.cs

143 lines
4.0 KiB
C#

using System;
using System.Threading;
namespace TellmePdmsPluging.Core
{
public static class MainThreadInvoker
{
public static InvokeResult Invoke(ICommand command, int timeoutMs)
{
if (command == null)
{
return new InvokeResult(false, null, new ArgumentNullException("command"), "command为空");
}
var wrapper = new ResultCommandWrapper(command);
SafeQueue.Enqueue(wrapper);
bool signaled = wrapper.Wait(timeoutMs);
if (!signaled)
{
return new InvokeResult(false, null, null, "等待PDMS主线程执行超时");
}
if (wrapper.Error != null)
{
return new InvokeResult(false, null, wrapper.Error, wrapper.Error.Message);
}
return new InvokeResult(true, wrapper.Result, null, null);
}
public static void InvokeAsync(ICommand command, Action<InvokeResult> onCompleted)
{
if (command == null)
{
if (onCompleted != null)
{
onCompleted(new InvokeResult(false, null, new ArgumentNullException("command"), "command为空"));
}
return;
}
var wrapper = new ResultCommandWrapper(command, onCompleted);
SafeQueue.Enqueue(wrapper);
}
private class ResultCommandWrapper : IResultCommand
{
private readonly ICommand _inner;
private readonly ManualResetEvent _done;
private readonly Action<InvokeResult> _onCompleted;
public ResultCommandWrapper(ICommand inner)
: this(inner, null)
{
}
public ResultCommandWrapper(ICommand inner, Action<InvokeResult> onCompleted)
{
_inner = inner;
_done = new ManualResetEvent(false);
_onCompleted = onCompleted;
CommandId = inner.CommandId;
}
public string CommandId { get; }
public string CommandType
{
get { return _inner.CommandType; }
}
public bool CanCancel
{
get { return _inner.CanCancel; }
}
public object Result { get; private set; }
public Exception Error { get; private set; }
public bool IsCompleted { get; private set; }
public object Execute()
{
try
{
Result = _inner.Execute();
return Result;
}
catch (Exception ex)
{
Error = ex;
return null;
}
finally
{
IsCompleted = true;
_done.Set();
if (_onCompleted != null)
{
try
{
_onCompleted(new InvokeResult(Error == null, Result, Error, Error == null ? null : Error.Message));
}
catch
{
// ignore callback errors
}
}
}
}
public void Cancel()
{
_inner.Cancel();
}
public bool Wait(int timeoutMs)
{
return _done.WaitOne(timeoutMs);
}
}
}
public class InvokeResult
{
public InvokeResult(bool success, object result, Exception error, string message)
{
Success = success;
Result = result;
Error = error;
Message = message;
}
public bool Success { get; }
public object Result { get; }
public Exception Error { get; }
public string Message { get; }
}
}