using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace NTwain { /// /// Allows work to be marshalled to a different (usually UI) thread if necessary. /// public interface IThreadMarshaller { /// /// Starts work asynchronously and returns immediately. /// /// void BeginInvoke(Delegate work, params object[] args); /// /// Starts work synchronously until it returns. /// /// /// /// object Invoke(Delegate work, params object[] args); } /// /// Doesn't actually use any particular thread. /// Should only be used in non-UI apps. /// public class NoParticularMarshaller : IThreadMarshaller { public bool InvokeRequired => throw new NotImplementedException(); public void BeginInvoke(Delegate work, params object[] args) { Task.Run(() => work.DynamicInvoke(args)); } public object Invoke(Delegate work, params object[] args) { return work.DynamicInvoke(args); } } /// /// Uses a winform UI thread to do the work. /// public class WinformMarshaller : IThreadMarshaller { private readonly System.Windows.Forms.Control _uiControl; /// /// Uses a control whose UI thread is used to run the work. /// /// public WinformMarshaller(System.Windows.Forms.Control uiControl) { _uiControl = uiControl ?? throw new ArgumentNullException(nameof(uiControl)); } public void BeginInvoke(Delegate work, params object[] args) { _uiControl.BeginInvoke(work, args); } public object Invoke(Delegate work, params object[] args) { return _uiControl.Invoke(work, args); } } /// /// Uses a WPF dispatcher to do the work. /// public class DispatcherMarshaller : IThreadMarshaller { private readonly System.Windows.Threading.Dispatcher _dispatcher; /// /// Uses a dispatcher whose UI thread is used to run the work. /// /// public DispatcherMarshaller(System.Windows.Threading.Dispatcher dispatcher) { _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher)); } public void BeginInvoke(Delegate work, params object[] args) { _dispatcher.BeginInvoke(work, args); } public object Invoke(Delegate work, params object[] args) { return _dispatcher.Invoke(work, args); } } }