You can absolutely create your own windows using WPF. But yes, you must be in a "UI stream" (which is an STA stream).
For example, let's say that we would like to have a property in our App class that provides some kind of window.
public partial class App { private static Window _myWindow; public static Window1 MyWindow { get { if (_myWindow == null) _myWindow = new Window1(); return _myWindow; } } }
The problem with this code, as you already found out, depending on which thread is causing the HTTP request, is disabled if the thread is not an STA.
To ensure that the window is created in the desired stream, enter a Dispatcher object . This object is used throughout WPF to ensure that communication between user interface elements is done in the correct thread.
Back to our new Window1 , we can use the App.Dispatcher object to make sure that the new operation is performed in the main thread of the application, for example:
public static Window1 MyWindow { get { if (_myWindow == null) { var window = Application.Current.Dispatcher.Invoke( new Func<Window1>(() => new Window1())); _myWindow = (Window1)window; } return _myWindow; } }
Here I get hold of the current Dispatcher object of the application and invokes Invoke using a delegate that does the actual novelty. Invoke guarantees that my delegate will be executed in the correct thread and will return the result. Voila, a window is created without a terrible STA error.
You should now bear in mind that further calls made to the MyWindow instance must also be made in the correct thread. To avoid clogging up your code with calls to Dispatcher.Invoke, it would be useful to wrap the window instance with a simple API. For example. The Show method can be implemented as follows: make sure that the marshal of calling Show is through the window's Dispatcher object:
public static void ShowMyWindow() { MyWindow.Dispatcher.Invoke(new Action(MyWindow.Show)); }
Peter Lillevold
source share