using System.Runtime.ExceptionServices;
using System.Windows.Forms;
namespace OpenNest.WinForms.Tests;
///
/// Runs a test body on its own STA thread and rethrows its failure on the
/// calling test thread.
///
///
/// By default WinForms catches an exception raised while dispatching a window
/// message or a BeginInvoke/SynchronizationContext callback and hands it to the
/// thread's ThreadException handler. With none registered it opens a modal
/// ThreadExceptionDialog in an interactive session, which blocks the test until
/// its join timeout, and silently ignores the exception otherwise. Both the
/// unhandled-exception mode and the handler are per-thread, so they cannot be
/// configured once for the assembly: each STA thread selects
/// before it creates a
/// window, and the exception then propagates to the code pumping messages
/// (Show, DoEvents, ShowDialog) and fails the test.
///
internal static class StaTestThread
{
public static void Run(Action body, TimeSpan timeout, string timeoutMessage)
{
Exception? failure = null;
var thread = new Thread(() =>
{
try
{
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
body();
}
catch (Exception ex)
{
failure = ex;
}
})
{
IsBackground = true,
};
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Assert.True(thread.Join(timeout), timeoutMessage);
if (failure != null)
ExceptionDispatchInfo.Capture(failure).Throw();
}
}