2011-04-06 124 views
4

我想要做的事:如何在单独的线程中打开一个窗口?

Window newWindow = new Window(); 
newWindow.Show(); 

while (true) 
{ 
    Console.Write("spin"); 
} 

也就是说,我做在主窗口中的密集计算,但是这个新窗口(这里我试图以显示与动画繁忙的指标)不响应(它的冷冻)...

于是,我就这样做:

Thread thread = new Thread(() => 
{ 
    Window newWindow = new Window(); 
    newWindow.Show(); 
}); 

thread.SetApartmentState(ApartmentState.STA); 
thread.Start(); 

while (true) 
{ 
    Console.Write("spin"); 
} 

但新的窗口仍然冻结等 任何人都知道什么是错在这里?

+1

为什么不只是在另一个线程上执行你的工作? – 2011-04-06 17:02:21

回答

8

您不应该尝试在自己的线程中打开一个新窗口。

相反,将您正在执行的计算工作推入后台线程,并使UI线程空闲。最简单的选择是使用BackgroundWorker。它会自动处理进度和完成回传到UI线程。

但是,您可以自己使用线程或Task/Task<T>来做到这一点。请记住使用从UI上下文创建的Dispatcher或TaskScheduler来处理任何会更新UI的任务,例如进度通知。

+0

“计算工作”实际上是一个正在显示的新窗口(除了newWindow)。我正在加载一个需要一段时间才能加载的新窗口。 – foreyez 2011-04-06 17:00:22

+1

@foreyez:通常可以通过“新窗口”将非UI计算移动到后台线程中,并完全避免此问题。 – 2011-04-06 17:02:09

+0

我认为他建议将新窗口的New或Load方法完成的工作放在新线程中。然后窗口可以打开并显示一条加载消息(如果在加载事件中) – Mike 2011-04-06 17:02:57

2

你不 - 只有一个GUI线程。如果你需要做阻塞工作,那东西必须在后台线程中。

2

您需要使用Application类在新线程中运行单独的消息循环。

+1

正确答案,不好的建议。 – 2011-04-06 17:52:07

+0

@亨克:是的;我意识到这是不好的建议。但是,其他答案已经涵盖了这一点。 – SLaks 2011-04-06 17:56:10

1

@SLaks如果您尝试从控制台应用程序启动一个新窗口,这可能非常有用。一种选择是使用showDialog();但是很难关闭它。

如果使用Show(),然后一个Application.run()(这是坚果和使用应用程序类,以启动一个新的消息循环的螺栓)当您在主控制台线程中调用Application.Exit()

,然后应用程序实际上关闭;

使用showDialog(),您必须中止该线程,然后等待窗口获得某种输入即鼠标悬停或焦点。否则它将永远退出。

相关问题