public static Task ShowWindowAndExecuteTests(SystemWindow initialSystemWindow, AutomationTest testMethod, double secondsToTestFailure = 30, string imagesDirectory = "", Action closeWindow = null) { var testRunner = new AutomationRunner(InputMethod, DrawSimulatedMouse, imagesDirectory); var resetEvent = new AutoResetEvent(false); // On load, release the reset event initialSystemWindow.Load += (s, e) => { resetEvent.Set(); }; int testTimeout = (int)(1000 * secondsToTestFailure); var timer = Stopwatch.StartNew(); bool testTimedOut = false; // Start two tasks, the timeout and the test method. Block in the test method until the first draw Task <Task> task = Task.WhenAny( Task.Delay(testTimeout), Task.Run(() => { // Wait until the first system window draw before running the test method, up to the timeout resetEvent.WaitOne(testTimeout); return(testMethod(testRunner)); })); // Once either the timeout or the test method has completed, store if a timeout occurred and shutdown the SystemWindow task.ContinueWith(innerTask => { long elapsedTime = timer.ElapsedMilliseconds; testTimedOut = elapsedTime >= testTimeout; // Invoke the callers close implementation or fall back to CloseOnIdle if (closeWindow != null) { closeWindow(); } else { initialSystemWindow.CloseOnIdle(); } }); // Main thread blocks here until released via CloseOnIdle above initialSystemWindow.ShowAsSystemWindow(); // Wait for CloseOnIdle to complete testRunner.WaitFor(() => initialSystemWindow.HasBeenClosed); if (testTimedOut) { // Throw an exception for test timeouts throw new TimeoutException("TestMethod timed out"); } // After the system window is closed return the task and any exception to the calling context return(task?.Result ?? Task.CompletedTask); }