private static bool trySpawnOnStaThread <TWindow, TArgs>(StaWindowThreadParams <TWindow, TArgs> myParams)
            where TWindow : Window
        {
            Dispatcher myDispatcher = null;

            try {
                SynchronizationContext.SetSynchronizationContext(
                    new DispatcherSynchronizationContext(
                        (myDispatcher = Dispatcher.CurrentDispatcher)));
                myParams.Window = myParams.Constructor(
                    myParams.ConstructorArgs != null
                                                        ? myParams.ConstructorArgs()
                                                        : default(TArgs));
                myParams.Window.Closed += WindowHelper.windowClosed;
            } catch (Exception ex) {
                Trace.TraceError(
                    $"{typeof(WindowHelper)} {nameof(WindowHelper.CreateWindowOnNewStaThread)}: "
                    + $"exception within ThreadStart. {ex}");
                if (myParams.Window != null)
                {
                    myParams.Window.Closed -= WindowHelper.windowClosed;
                    try {
                        myParams.Window.Close();
                    } catch {
                        // Ignored
                    }
                }
                try {
                    myDispatcher?.InvokeShutdown();
                } catch {
                    // Ignored
                }
                myParams.Window = null;
                myParams.Error  = ex;
                return(false);
            } finally {
                myParams.Gate.Set();
            }
            return(true);
        }
 /// <summary>
 /// Creates a new STA Background Thread, which sets a <c>SynchronizationContext</c>
 /// with a <c>Dispatcher</c>. Then constructs a new <c>Window</c> on the Thread,
 /// using the <c>constructor</c> <c>Func</c> and any <c>constructorArgs</c>. Then
 /// the Thread runs the <c>Dispatcher</c> and this method returns the <c>Window</c>.
 /// The <c>Dispatcher</c> listens for <c>window.Closed</c> and invokes
 /// <c>BeginInvokeShutdown</c>. The <c>constructorArgs</c> is provided as a <c>Func</c>
 /// so that it will be invoked on the <c>Window's</c> Thread: the object you return
 /// is passed to your <c>constructor</c> (and has been created on that Thread). This
 /// may be null.
 /// </summary>
 /// <typeparam name="TWindow">Your Window Type.</typeparam>
 /// <typeparam name="TArgs">Constructor's argument type</typeparam>
 /// <param name="constructor">Construct and return your Window.</param>
 /// <param name="constructorArgs">Optional args for your constructor Func. If this
 /// argument is not null, it will be invoked on the new Thread, and the result
 /// is passed to your <c>constructor</c>. If this is null, your constructor receives
 /// <c>default(TArgs)</c>.</param>
 /// <param name="error">This must be checked. If not null, the result will
 /// be null.</param>
 public static TWindow CreateWindowOnNewStaThread <TWindow, TArgs>(
     Func <TArgs, TWindow> constructor,
     Func <TArgs> constructorArgs,
     out Exception error) where TWindow : Window
 {
     using (StaWindowThreadParams <TWindow, TArgs> threadParams
                = new StaWindowThreadParams <TWindow, TArgs>(constructor, constructorArgs)) {
         Thread newWindowThread = new Thread(
             tp => {
             if (WindowHelper.trySpawnOnStaThread((StaWindowThreadParams <TWindow, TArgs>)tp))
             {
                 Dispatcher.Run();
             }
         });
         newWindowThread.SetApartmentState(ApartmentState.STA);
         newWindowThread.IsBackground = true;
         newWindowThread.Start(threadParams);
         threadParams.Gate.WaitOne();
         error = threadParams.Error;
         return(threadParams.Window);
     }
 }