Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Starting a WPF window from a class library project

Tags:

c#

wpf

I'm creating a sort of "loading screen" that will be shown from the class library just before some heavy processing, and then it will hide when the processing has finished. My problem is that no matter what I do, the heavy processing seems to be blocking the UI thread. I've had to set the methods with the [STAThread] attribute so the window actually gets created. I then show the window using:

bw = new BusyWindow();
bw.Show();

And then simply hide it with bw.Hide() when the processing is done. I've created a Task for the processing so it should be running on a separate thread..? Unless, of course, the STAThread completely messes it up?

Some more code:

var taskStart = Task.Factory.StartNew(() => ShowBusyWindow());
var taskProcess = taskStart.ContinueWith((antecedent) => GetInternal());
var taskEnd = taskProcess.ContinueWith((antecedent) => HideBusyWindow());

return taskProcess.Result;

And ShowBusywindow

public void ShowBusyWindow()
        {
            bw = new BusyWindow();
            bw.Show();
        }

And HideBusyWindow:

public void HideBusyWindow()
        {
            bw.Close();
        }

I should also mention that I am trying to expose this library to COM, so it can be run from some VB6 code. I don't know if this has any affect on anything...?

like image 212
Harry Avatar asked Apr 08 '11 11:04

Harry


1 Answers

Ok, so a WPF window can be called from a class library or any other thread by using the following method:

thread = new Thread(() =>
        {
            bw = new BusyWindow();
            bw.Show();
            bw.Closed += (s, e) => bw.Dispatcher.InvokeShutdown(); 
            Dispatcher.Run();
        });
        thread.SetApartmentState(ApartmentState.STA);
        //thread.IsBackground = true;
        thread.Start();

You don't really need the IsBackground for this. The only need for it is if the thread Dispatcher isn't shut down when the window closes. It would create a "ghost thread" if it wasn't shut down.

Apartment state obviously has to be set to STA so the Window can actually get created. According to this website, single-thread WPF windows can be useful for very UI intensive windows (lots of graphs etc).

To close the window I simply called thread.Abort(). I don't think this is the cleanest way to do it, but it works for what I need.

like image 83
Harry Avatar answered Oct 14 '22 07:10

Harry