当我启动主线程时,我也启动了第二个线程,但第二个线程仍在等待主线程。我期望当我开始一个新线程时,它将在没有连接到主线程的情况下继续工作。那么为什么panel1
在主线完成其工作后变得可见?
private void comboBox1_SelectedIndexChanged_1(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(threadUI));
thread.Start();
// This class is loading something from the server on the main thread
excel.get_data_from_excel(comboBox1.SelectedItem.ToString(), this);
}
private void threadUI()
{
if (panel1.InvokeRequired)
{
panel1.Invoke(new newDelegate(threadUI));
}
else
{
panel1.Visible = true;
}
}
答案 0 :(得分:5)
在主线程执行委托之前,Invoke
方法不会返回。如果您希望后台线程继续而不等待主线程,请改为使用BeginInvoke
。
但是,请注意主线程上只能发生一件事。您可以调用Invoke或BeginInvoke,但在主线程空闲之前不会处理该委托。也就是说,如果get_data_from_excel需要很长时间,那么在get_data_from_excel完成之前,panel1.Visible=true
将不会生效,comboBox1_SelectedIndexChanged_1将返回,并且主线程将变为空闲。
如果你真的想让这些东西“平行”,你必须在后台线程中执行get_data_from_excel。
答案 1 :(得分:1)
你正在UI线程中长时间运行非UI工作。
你创建的第二个线程除了调用Invoke
并做一些工作外什么都不做。 Invoke
做什么在UI线程中运行一些代码,当前正在忙于做一些非UI工作。它将不会安排在该工作完成之后运行。
你应该做的是在另一个线程而不是UI线程中进行长时间运行的非UI工作。
答案 2 :(得分:0)
您似乎对Invoke()
感到困惑。
Invoke()
用于为显示panel1
的线程排队委托。但是,Invoke()
会阻止UNTIL 该委托已完成运行。因此,您在Invoke()
处阻止了第二个线程。
如果你想在主线程上运行一个动作,同时从第二个线程没有阻止调用它...然后使用BeginInvoke()
。它会将代表排队,然后立即返回。
Servy的评论
Servy提出了一个很好的观点。什么是第二个线程的重点,如果它只是立即调用第一个?如果您要立即调整控件的属性,则无需创建第二个线程。
但看起来你正在从excel中获取数据。该部分代码应位于第二个帖子中......然后使用它BeginInvoke()
输出。
答案 3 :(得分:0)
如果我使用这样的代码,它也在等待完整的下一个 线完成其工作
private void comboBox1_SelectedIndexChanged_1(object sender, EventArgs e)
{
panel1.Visible = true;
excel.get_data_from_excel(comboBox1.SelectedItem.ToString(), this);
}