Fix System.InvalidOperationException Dispatcher job loop detected (#20310)
This commit is contained in:
@@ -142,20 +142,25 @@ public static class HeadlessWindowExtensions
|
||||
action(GetImpl(topLevel));
|
||||
RunJobsAndRender();
|
||||
|
||||
void RunJobsAndRender()
|
||||
static void RunJobsAndRender()
|
||||
{
|
||||
var count = 0;
|
||||
var dispatcher = Dispatcher.UIThread;
|
||||
|
||||
while (dispatcher.HasJobsWithPriority(DispatcherPriority.MinimumActiveValue))
|
||||
// Run jobs and render frames until everything is stable.
|
||||
// We use a simple approach: run jobs, render, and repeat until
|
||||
// there are no more pending jobs. The render timer tick can schedule
|
||||
// new jobs, so we loop until stable.
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
if (count >= 10)
|
||||
throw new InvalidOperationException("Dispatcher job loop detected");
|
||||
|
||||
dispatcher.RunJobs();
|
||||
AvaloniaHeadlessPlatform.ForceRenderTimerTick();
|
||||
++count;
|
||||
|
||||
if (!dispatcher.HasJobsWithPriority(DispatcherPriority.MinimumActiveValue))
|
||||
return;
|
||||
}
|
||||
|
||||
// Final attempt: run remaining jobs without rendering
|
||||
dispatcher.RunJobs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,37 @@ public class InputTests
|
||||
Assert.True(_window.Position == newWindowPosition);
|
||||
}
|
||||
|
||||
#if NUNIT
|
||||
[AvaloniaTest, Timeout(10000)]
|
||||
#elif XUNIT
|
||||
[AvaloniaFact]
|
||||
#endif
|
||||
public void Should_Click_Button_After_Explicit_RunJobs()
|
||||
{
|
||||
// Regression test for https://github.com/AvaloniaUI/Avalonia/issues/20309
|
||||
// Ensure that calling Dispatcher.UIThread.RunJobs() before MouseDown does not throw
|
||||
var button = new Button { Content = "Test content" };
|
||||
_window.Content = button;
|
||||
_window.Show();
|
||||
|
||||
Dispatcher.UIThread.RunJobs();
|
||||
|
||||
var clickCount = 0;
|
||||
button.Click += (_, _) => clickCount++;
|
||||
|
||||
var point = new Point(button.Bounds.Width / 2, button.Bounds.Height / 2);
|
||||
var translatePoint = button.TranslatePoint(point, _window);
|
||||
|
||||
// Move
|
||||
_window.MouseMove(translatePoint!.Value, RawInputModifiers.None);
|
||||
|
||||
// Click
|
||||
_window.MouseDown(translatePoint.Value, MouseButton.Left, RawInputModifiers.None);
|
||||
_window.MouseUp(translatePoint.Value, MouseButton.Left, RawInputModifiers.None);
|
||||
|
||||
Assert.True(clickCount == 1);
|
||||
}
|
||||
|
||||
#if NUNIT
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
|
||||
Reference in New Issue
Block a user