So, if I understood your question correctly, you say that this code works exactly the way you want, but you are just trying to understand how (and why) it works?
Here's how it works. Firstly, your thread executes this code:
Application.Current.Dispatcher.BeginInvoke(new Action(() => { window = new Window(); window.ShowDialog(); }));
This is the sequence of your actions in the main dispatch queue (UI), and then immediately returns: the workflow continues to work.
When you first launch the application (usually using code generated by the compiler that initializes your App.xaml object, although you can also do this explicitly by calling Application.Run), it starts its message loop, which looks something like this: (pseudocode very very simplified):
public class Application { public void Run() { while (!Exited && action = Dispatcher.DequeueAction()) action(); } }
So, at some point, soon after you put the queue into action, the user interface thread will bypass to pull your action out of the queue and run it, after which your action will create a window and show it modally.
Now the modal window starts its own message loop, which looks something like this (again, very simplified):
public class Window { public bool? ShowDialog() { DisableOtherWindowsAndShow(); while (!IsClosed && action = Dispatcher.DequeueAction()) action(); EnableOtherWindowsAndHide(); return DialogResult; } }
Later, your worker thread runs this code:
Application.Current.Dispatcher.BeginInvoke(new Action(() => { window.Close(); }));
Again, your action is queued up on the UI thread manager queue, and then the BeginInvoke call returns immediately and the workflow continues to work.
So sooner or later the message loop of the user interface stream will get by and begin to perform your action, which indicates the closing of the window. This has the same effect as the user clicking the βXβ button in the title bar, which, of course, works great even if you are in a modal dialog box. This leads to the end of the ShowDialog message loop (because the window is now closed), after which the dialog is hidden and the other windows are turned on again, ShowDialog returns, the original action (ShowDialog) is completed and therefore returns, and control drops back to the original message outline in the Application .Run.
Note that in each thread there is one dispatch queue, and not one message line. Thus, your "closed" action goes in the same queue as the "show dialogue" action. This is another piece of code that now polls as a message loop (one inside ShowDialog instead of one inside Application.Run), but the basics are the same.