2014-01-08 131 views
0

当我启动主线程时,我也启动了第二个线程,但第二个线程仍然等待主线程。我期望当我开始一个新的线程时,它会在没有连接到主线程的情况下工作。那么为什么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; 
     } 
    } 

回答

5

Invoke方法将不会返回,直到主线程执行委托。如果您希望后台线程在不等待主线程的情况下继续,请改为使用BeginInvoke

但是,请注意,主线程上只能发生一件事。您可以调用Invoke或BeginInvoke,但在主线程闲置之前不会处理委托。也就是说,如果get_data_from_excel需要很长时间,则在get_data_from_excel完成之前,panel1.Visible=true才会生效,comboBox1_SelectedIndexChanged_1返回,并且主线程变为空闲状态。

如果你真的想让这些东西“并行”,你必须在后台线程中执行get_data_from_excel。

+0

我将那行改成这样:PANEL1。BeginInvoke(new newDelegate(threadUI)); //但它仍在等待mainThread变为可见 – Toprak

+3

这不会帮助他解决他的问题。如果没有通过使用'BeginInvoke'阻止第二个线程将会修改问题的一个症状而不解决根本问题。 – Servy

+1

查看我的编辑。我认为你有比Invoke/BeginInvoke更大的问题。 –

1

您正在UI线程中长时间运行非UI工作。

你创建的第二个线程除了调用Invoke并且做了一些工作之外什么都不做。什么Invoke确实在UI线程中运行了一些代码,目前它正忙于做一些非UI工作。它不会计划在该工作完成之后运行。

你应该做的是在另一个线程中做非常长的非UI工作,而不是UI线程。

0

看起来你对Invoke()感到困惑。

Invoke()用于排队显示panel1的线程的委托。但是,Invoke()块UNTIL委托已运行完成。因此,您的第二个线程阻止在Invoke()

如果您希望在主线程上运行一个动作,同时从第二个线程调用它而不阻止 ...然后使用BeginInvoke()。它会排队委托,然后立即返回。

Servy的评论

Servy带来了一个好点。第二个线程的意义是什么,如果它只是立即调用第一个线程?如果您要立即调整控件的属性,则不需要创建第二个线程。

但它看起来像你从Excel中抓取数据。该代码段应该在第二个线程中,然后输出使用BeginInvoke()

+0

这不会帮助他解决他的问题。如果没有通过使用'BeginInvoke'阻止第二个线程将会修改问题的一个症状而不解决根本问题。 – Servy

+0

@Servy你是对的。我调整了答案。 – Andrew

0

如果我使用的代码就这样它也在等待下一个完整的行 完成其工作

private void comboBox1_SelectedIndexChanged_1(object sender, EventArgs e) 
{ 
    panel1.Visible = true; 
    excel.get_data_from_excel(comboBox1.SelectedItem.ToString(), this); 
} 
+0

我现在这是一个强化问题,但我也是新的C#,并试图找出它 – Toprak

+0

在这里,你仍然阻塞UI线程,所以面板的可见性将不会改变,直到操作完成后。 – Servy