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:
我正在创建一种“加载屏幕”,它将在一些繁重的处理之前从类库中显示出来,然后它将在处理完成时隐藏。我的问题是,无论我做什么,繁重的处理似乎都阻止了UI线程。我必须使用[STAThread]属性设置方法,以便实际创建窗口。然后我使用以下方式显示窗口:
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?
然后在处理完成后用bw.Hide()隐藏它。我已经为处理创建了一个任务,所以它应该在一个单独的线程上运行..?当然,除非STAThread完全混乱了吗?
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...?
我还要提一下,我正在尝试将此库公开给COM,因此可以从某些VB6代码运行它。我不知道这对任何事都有影响......?
1 个解决方案
#1
5
Ok, so a WPF window can be called from a class library or any other thread by using the following method:
好的,所以可以使用以下方法从类库或任何其他线程调用WPF窗口:
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.
你真的不需要IsBackground。唯一需要的是当窗口关闭时线程Dispatcher没有关闭。如果它没有关闭,它会创建一个“鬼线”。
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).
公寓状态显然必须设置为STA,因此Window实际上可以创建。根据这个网站,单线程WPF窗口可用于非常密集的UI窗口(许多图形等)。
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.
要关闭窗口,我只需调用thread.Abort()。我不认为这是最干净的方法,但它适用于我需要的东西。
#1
5
Ok, so a WPF window can be called from a class library or any other thread by using the following method:
好的,所以可以使用以下方法从类库或任何其他线程调用WPF窗口:
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.
你真的不需要IsBackground。唯一需要的是当窗口关闭时线程Dispatcher没有关闭。如果它没有关闭,它会创建一个“鬼线”。
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).
公寓状态显然必须设置为STA,因此Window实际上可以创建。根据这个网站,单线程WPF窗口可用于非常密集的UI窗口(许多图形等)。
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.
要关闭窗口,我只需调用thread.Abort()。我不认为这是最干净的方法,但它适用于我需要的东西。