diff --git a/src/ReactiveMvvm.Terminal/Program.cs b/src/ReactiveMvvm.Terminal/Program.cs index 0d3040d..2889499 100644 --- a/src/ReactiveMvvm.Terminal/Program.cs +++ b/src/ReactiveMvvm.Terminal/Program.cs @@ -1,8 +1,10 @@ using System; +using System.Reactive.Concurrency; using ReactiveMvvm.Services; using ReactiveMvvm.Terminal.Services; using ReactiveMvvm.Terminal.Views; using ReactiveMvvm.ViewModels; +using ReactiveUI; using Terminal.Gui; namespace ReactiveMvvm.Terminal @@ -12,6 +14,8 @@ public static class Program public static void Main(string[] args) { Application.Init(); + RxApp.MainThreadScheduler = TerminalScheduler.Default; + RxApp.TaskpoolScheduler = TaskPoolScheduler.Default; Application.Run( new FeedbackView( new( diff --git a/src/ReactiveMvvm.Terminal/TerminalScheduler.cs b/src/ReactiveMvvm.Terminal/TerminalScheduler.cs new file mode 100644 index 0000000..7e2997b --- /dev/null +++ b/src/ReactiveMvvm.Terminal/TerminalScheduler.cs @@ -0,0 +1,60 @@ +using System; +using System.Reactive.Concurrency; +using System.Reactive.Disposables; +using Terminal.Gui; + +namespace ReactiveMvvm; + +public class TerminalScheduler : LocalScheduler +{ + public static readonly TerminalScheduler Default = new (); + private TerminalScheduler () { } + + public override IDisposable Schedule ( + TState state, + TimeSpan dueTime, + Func action + ) + { + IDisposable PostOnMainLoop () + { + var composite = new CompositeDisposable (2); + var cancellation = new CancellationDisposable (); + + Application.Invoke ( + () => + { + if (!cancellation.Token.IsCancellationRequested) + { + composite.Add (action (this, state)); + } + } + ); + composite.Add (cancellation); + + return composite; + } + + IDisposable PostOnMainLoopAsTimeout () + { + var composite = new CompositeDisposable (2); + + object timeout = Application.AddTimeout ( + dueTime, + () => + { + composite.Add (action (this, state)); + + return false; + } + ); + composite.Add (Disposable.Create (() => Application.RemoveTimeout (timeout))); + + return composite; + } + + return dueTime == TimeSpan.Zero + ? PostOnMainLoop () + : PostOnMainLoopAsTimeout (); + } +}