<PackageReference Include="System.Reactive" Version="4.3.1" />

ControlScheduler

Represents an object that schedules units of work on the message loop associated with a Windows Forms control.
using System.Reactive.Disposables; using System.Threading; using System.Windows.Forms; namespace System.Reactive.Concurrency { public class ControlScheduler : LocalScheduler, ISchedulerPeriodic { private readonly Control _control; public Control Control => _control; public ControlScheduler(Control control) { if (control == null) throw new ArgumentNullException("control"); _control = control; } public override IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action) { if (action == null) throw new ArgumentNullException("action"); if (_control.get_IsDisposed()) return Disposable.Empty; SingleAssignmentDisposable d = new SingleAssignmentDisposable(); _control.BeginInvoke((Delegate)(Action)delegate { if (!_control.get_IsDisposed() && !d.IsDisposed) d.Disposable = action(this, state); }); return d; } public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action) { if (action == null) throw new ArgumentNullException("action"); TimeSpan dt = Scheduler.Normalize(dueTime); if (dt.Ticks == 0) return Schedule(state, action); Func<IScheduler, TState, IDisposable> func = delegate(IScheduler scheduler1, TState state1) { MultipleAssignmentDisposable d = new MultipleAssignmentDisposable(); Timer timer = new Timer(); timer.add_Tick((EventHandler)delegate { Timer val2 = Interlocked.Exchange<Timer>(ref timer, null); if (val2 != null) try { if (!_control.get_IsDisposed() && !d.IsDisposed) d.Disposable = action(scheduler1, state1); } finally { val2.Stop(); action = null; } }); timer.set_Interval((int)dt.TotalMilliseconds); timer.Start(); d.Disposable = Disposable.Create(delegate { Timer val = Interlocked.Exchange<Timer>(ref timer, null); if (val != null) { val.Stop(); action = ((IScheduler _, TState __) => Disposable.Empty); } }); return d; }; if (_control.get_InvokeRequired()) return Schedule(state, func); return func(this, state); } public IDisposable SchedulePeriodic<TState>(TState state, TimeSpan period, Func<TState, TState> action) { if (period.TotalMilliseconds < 1) throw new ArgumentOutOfRangeException("period"); if (action == null) throw new ArgumentNullException("action"); Func<IScheduler, TState, IDisposable> func = delegate(IScheduler scheduler1, TState state1) { Timer timer = new Timer(); timer.add_Tick((EventHandler)delegate { if (!_control.get_IsDisposed()) state1 = action(state1); }); timer.set_Interval((int)period.TotalMilliseconds); timer.Start(); return Disposable.Create(delegate { Timer val = Interlocked.Exchange<Timer>(ref timer, null); if (val != null) { val.Stop(); action = ((TState _) => _); } }); }; if (_control.get_InvokeRequired()) return Schedule(state, func); return func(this, state); } } }