在其他线程上加载WinForms

时间:2011-09-02 04:11:50

标签: c#-4.0

像许多其他人一样,我需要在其他线程上打开WinForms。在阅读了很多不同的文章之后,我发现这是不可能的,但我的问题是,它是否可以一次实现或者有没有办法实现以下目标?

我正在创建一个具有很多工具窗口的应用程序,这些工具窗口很难初始化(因为许多控件或其他无法放在工作线程上的东西)并且在主应用程序启动时不需要立即使用这些工具窗口但是我还想在他们准备好使用时向他们展示。

这是否有可能以某种方式实现,而不需要其他线程上的WinForms功能,现在接缝是不可能的?

提前致谢

修改

大家好,感谢你们提供了很好的文章和提示,但是我没有提供关于我的真实内容的更多细节,这是我的错误。我目前正在使用第三方控件,使我能够在MDI容器中打开WinForms作为选项卡式窗口(我正在使用Telerik.WinControls.UI.Docking.RadDock)。为此,主UI空间线程(承载RadDock的线程)需要被告知新添加的Winforms能够将它们添加到“选项卡式”窗口列表中。这是我不知道如何完成的事情之一,因为这将涉及我在另一个线程上创建的工具窗口之一,可以编组并在主线程上使用。

2 个答案:

答案 0 :(得分:2)

它不是你需要在其他线程上显示你的WinForms,而是需要使这些表单内的工作异步并实现正确的线程安全同步。我有两篇适用于此的博客文章。

两者都适用于Windows窗体,并且在使WinForms异步时可以找到大量文章。

例如,

ToolWindowForm form = new ToolWindowForm()) {
form.Show();
// other code

假设您在代码中的某处需要使用此工具窗口进行显示,但是加载它会花费很长时间来阻止执行其余代码。好吧,在另一个线程上显示表单可能是实现此目的的一种方法,并且非常可能。然而,如果你在表单之间进行通信并需要访问控件,那么你将会遇到CrossThreadViolations和IllegalCrossThreadCalls。只是为了使每个表单后面的工作异步,它更容易和更安全。

修改 如果必须,您可以添加私有成员来将实例存储到表单,即

private Form m_MyToolForm = new Form();
private Form m_MyToolForm2 = new Form();

然后在代码的某处。

public void ShowToolForm() {
    Thread thread = new Thread(new ThreadStart(ShowToolFormAsync));
    thread.IsBackground = true;
    thread.Start();
}  

private void ShowToolFormAsync() {
    m_MyToolForm.ShowDialog(); // Blocks on this thread
}

如果您使用的是.NET 4,也可以使用任务并行库。

Task.Factory.StartNew(() => m_MyToolForm.ShowDialog());

答案 1 :(得分:0)

我似乎不可能这样做。 在不同的线程上创建表单和更新表单控件的唯一大问题, 是你需要一个线程安全的回调,否则你会得到错误,只有创建表单的父线程才能更新gui。

有关此线程安全回调的更多信息以及此交叉线程所需的InvokeRequired内容,请访问:http://msdn.microsoft.com/en-us/library/ms171728%28v=vs.80%29.aspx