我有一个Windows窗体应用程序(Form1),允许用户打开另一个窗体(FormGraph)。为了打开FormGraph应用程序,我使用一个打开它的线程 这是线程正在运行的代码:
private void ThreadCreateCurvedGraph()
{
FormGraph myGraph = new FormGraph();
myGraph.CreateCurvedGraph(...);
myGraph.Show();
}
我的问题是myGraph
在它打开后立即关闭
1)有谁知道为什么会这样,以及如何让myGraph
保持开放?
2)用户关闭myGraph
后,如何终止线程?
非常感谢!
答案 0 :(得分:5)
问题不在发布的代码段中。您需要使用Application.Run()或Form.ShowDialog()启动新的消息循环。您还需要处理线程属性,因此适合充当UI线程。例如:
Thread t = new Thread(() => {
Application.Run(new Form2());
// OR:
//new Form2().ShowDialog();
});
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
这里有一些尴尬的选择。表单不能由主线程上的任何表单拥有,这通常会导致Z顺序问题。当UI线程的主窗体关闭时,您还需要做一些有意义的事情。通过使用IsBackground来解决这个问题。
Windows旨在支持在一个线程上运行的多个窗口。如果确实必须使用,请仅使用此类代码。你永远不应该......
答案 1 :(得分:1)
您遇到的主要问题是您没有在新线程中建立消息泵。
检查
详细了解如何使用多个线程(每个表单/表单组一个)运行高性能用户界面。
你基本上错过了对Application.Run的调用,以便在单独的UI线程上设置消息泵。
我认为一旦消息泵的最后一种形式关闭 - 它将自行处理并结束。
请注意,所有这些假设你想在一个单独的UI线程中打开窗口...否则你需要调用回主UI线程来创建窗口的所有操作,所以它会附加到现有的消息泵。两者都有好的情况 - 一个保持简单,另一个允许更多的性能,因为每个窗口都有一个单独的消息泵,因此可以单独行动 - 这例如在交易应用程序中使用很多,可能需要更新图表如果在UI中运行单线程,则会有许多屏幕和瓶颈。
答案 2 :(得分:0)
不要在非主线程中创建和显示表单。在主表单线程中执行。
或者这样做:
private void ThreadCreateCurvedGraph()
{
FormGraph myGraph = new FormGraph();
myGraph.CreateCurvedGraph(...);
Application.Run(myGraph);
}
但第一版更好
答案 3 :(得分:0)
根据经验,你应该避免从线程操纵UI(创建表单是对UI的一种操作)。您应该始终从主线程操纵UI。
答案 4 :(得分:0)
如果为表单准备数据需要一段时间,您可以在单独的线程中执行此操作以使应用程序保持响应。数据准备好后,您可以将对象返回到主线程,让它显示它。
您应该为表单中的对象声明一个变量,而不是在方法中为本地声明,以便在退出线程时它能够存活。
当您准备好显示表单时,可以使用Invoke方法进行将在主线程中执行的方法调用。
答案 5 :(得分:0)
表单正在关闭,因为该线程已完成,因此随其资源(表单)一起被释放。要使线程保持运行,您需要一个循环
e.g。
private void ThreadCreateCurvedGraph()
{
FormGraph myGraph = new FormGraph();
myGraph.CreateCurvedGraph(...);
myGraph.Show();
while (myGraph.IsOpen)
{
//process incoming messages <- this could be fun on a thread....
}
}
你需要一个设置IsOpen的方法(比如超时或按钮),显然你需要实际创建IsOpen作为表单的属性,并在创建表单时将其设置为true。
我会在这里添加与其他用户相同的...你应该有充分的理由不使用主线程。
答案 6 :(得分:0)
为什么要在新线程上创建表单?有时您需要使用新线程,但有时您可以在主线程上使用form.ShowDialog()。
答案 7 :(得分:-1)
也许这就是垃圾收集:
退出ThreadCreateCurvedGraph()
后,myGraph
超出范围并关闭。
你需要组织一个线程的方式来保持实例并等待(使用阻塞等待)它关闭。
编辑例如添加:
Application.Run(myGraph)
到方法结束。
(见TomTom的评论)
答案 8 :(得分:-1)
如果您将表单显示为对话框怎么办?你可以使用
private void ThreadCreateCurvedGraph()
{
FormGraph myGraph = new FormGraph();
myGraph.CreateCurvedGraph(...);
myGraph.ShowDialog();
}
这样调用将阻塞,直到myGraph表单关闭。正如你在一个独立的线程上创建的myGraph一样,调用阻塞的ShowDialog应该只阻止那个线程。