internal override void Start(IWinMessageFilter filter)
 {
     if (_dispatcher == null)
     {
         // using this hack so the new thread will start running before this function returns
         using (var hack = new WrappedManualResetEvent())
         {
             var loopThread = new Thread(new ThreadStart(() =>
             {
                 PlatformInfo.Current.Log.Debug("NTwain internal message loop is starting.");
                 _dispatcher = Dispatcher.CurrentDispatcher;
                 if (!PlatformInfo.Current.IsOnMono)
                 {
                     _hook  = new WindowsHook(filter);
                     Handle = _hook.Handle;
                 }
                 hack.Set();
                 Dispatcher.Run();
                 // if dispatcher shutsdown we'll get here so make everything uninitialized
                 _dispatcher = null;
                 if (_hook != null)
                 {
                     _hook.Dispose();
                     _hook  = null;
                     Handle = IntPtr.Zero;
                 }
             }));
             loopThread.IsBackground = true;
             loopThread.SetApartmentState(ApartmentState.STA);
             loopThread.Start();
             hack.Wait();
         }
     }
 }
        public override void Invoke(Action action)
        {
            if (_dispatcher == null)
            {
                throw new InvalidOperationException(Resources.MsgLoopUnavailble);
            }

            Exception error = null;

            if (_dispatcher.CheckAccess())
            {
                action();
            }
            else if (PlatformInfo.Current.IsOnMono)
            {
                using (var man = new WrappedManualResetEvent())
                {
                    _dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
                    {
                        try
                        {
                            action();
                        }
                        catch (Exception ex) { error = ex; }
                        finally
                        {
                            man.Set();
                        }
                    }));
                    man.Wait();
                }
            }
            else
            {
                _dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
                {
                    try
                    {
                        action();
                    }
                    catch (Exception ex) { error = ex; }
                }));
            }

            if (error != null)
            {
                Rethrow(error);
            }
        }