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 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 _onCompleted; public ResultCommandWrapper(ICommand inner) : this(inner, null) { } public ResultCommandWrapper(ICommand inner, Action 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; } } }