Terminal.Gui icon indicating copy to clipboard operation
Terminal.Gui copied to clipboard

Idles are just timeouts with Timespan.Zero

Open tznind opened this issue 6 months ago • 3 comments

We draw a distinction between timeouts and idles but in practice they both run once per iteration.

An Idle is just a timeout with TimeSpan.Zero.

All the interface distinctions around lamdas and add/remove idle can be vastly simplified by just replacing with:

        ml.TimedEvents.AddTimeout (TimeSpan.Zero, someFunc);

I've started a PR that seems to suggest this is feasible to simplify ITimedEvents considerably. This is required first step because I want to add the ability to have more exciting time systems e.g. also Logarithmic (for #4123 ). Timeout doesn't explicitly always have to be the same time over and over.

tznind avatar Jun 19 '25 19:06 tznind

That also works well with SynchronizationContext?

BDisp avatar Jun 19 '25 19:06 BDisp

That also works well with SynchronizationContext?

Seems all the tests pass

Except Mainloop_Invoke_Or_AddTimeout_Can_Be_Used_For_Events_Or_Actions which hangs on one of its cases.

The test is confusing:

// Passes
Action a1 = StartWindow;

// Infinite loop
Action a2 = () => Application.Invoke (StartWindow);

The test is very confusing but seems to want to do the following:

  • Run a Toplevel (top)
  • Click a button after a short time (btnLaunch) that opens another window

It then tries to click a btn on that launched window which will ... do something

Then it wants the ContinueWith to happen and set taskCompleted which then makes original iteration event close the popped up window.

                  .ContinueWith (
                                 async (s, e) =>
                                 {
                                     await Task.Delay (1000);
                                     Assert.Equal (clickMe, btn.Text);
                                     Assert.Equal (three, total);

                                     Interlocked.Increment (ref total);

                                     Assert.Equal (clickMe, btn.Text);
                                     Assert.Equal (four, total);

                                     taskCompleted = true;
                                 },
                                 TaskScheduler.FromCurrentSynchronizationContext ()
                                );

I don't understand how this used to work and doesn't with timeouts given they are almost identical in implementation.

A simpler example that repros the issue would be very useful.

tznind avatar Jun 20 '25 03:06 tznind

Put a breakpoint in the Post method to see if it's hit. Application.AddTimeout always run in the UIThread.

BDisp avatar Jun 20 '25 07:06 BDisp