143 lines
4.0 KiB
C#
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; }
|
|
}
|
|
}
|