/// <summary> /// Opens a new window on it's own thread and shows it. /// </summary> /// <remarks> /// Make sure to access this window using Window.Dispatcher.BeginInvoke. /// </remarks> /// <param name="path">Optional photo to open in new window.</param> /// <returns>The new Window.</returns> private void OpenPhotoWindowOnNewThread(PhotoWindowData?data = null) { Thread thread = new Thread(() => { PhotoWindow window = (data != null) ? new PhotoWindow(new PhotoWindowViewModel(data)) : new PhotoWindow(); window.Closed += (s, e) => window.Dispatcher.InvokeShutdown(); photoWindows.Add(window); window.Show(); Dispatcher.Run(); }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); }
public void Add(PhotoWindow window) { /* * Dispatching to window thread so that it will be in the correct thread-local collection, * also this makes the combination of adding the window and hooking up the closed event * effectively atomic since close and the closed event are only called on the ui thread. */ window.Dispatcher.BeginInvoke(() => { LinkedList <PhotoWindow> windowsForThisThread = threadLocalWindows.Value !; int cachedCloseState; lock (windowsForThisThread) { cachedCloseState = closeAllForever; /* * Need to check closeAllForever inside lock because we don't want * a thread setting it and closing our thread local windows * between this check and this add, otherwise the window will be * added too late and not closed. */ if (cachedCloseState == CLOSE_FOREVER_OFF) { windowsForThisThread.AddLast(window); } } switch (cachedCloseState) { case CLOSE_FOREVER_OFF: window.Closed += WindowClosed; break; case CLOSE_FOREVER_ON_PERSIST: window.Close(true); break; case CLOSE_FOREVER_ON_DONT_PERSIST: window.Close(false); break; } }); }