工作线程上的调用方法来自UI线程

时间:2013-01-28 20:59:05

标签: c# winforms multithreading

使用C#在Winforms中工作,我有一个主窗体,可以在单独的线程上创建第二个UI窗体。

viewThread = new Thread( ( ) => 
{ 
  views = new Views.Views( displayRotators, screenLocationLeft, screenLocationTop, screenHeight, screenWidth );
  Application.Run( views );
} );
viewThread.SetApartmentState( ApartmentState.STA );
viewThread.Start( );

在第二个UI表单上,我现在需要调用一个方法来启动一个显示循环,该循环将一直运行直到我终止该线程。我花了大约三个小时试图找到一种方法来做到这一点,但我能找到的只是从工作线程调用主UI线程上的方法的示例,而不是调用工作线程上的方法来自主UI线程。谁能告诉我怎么做到这一点?

感谢。

2 个答案:

答案 0 :(得分:3)

在极少数情况下,运行多个UI线程确实很有意义。除非你有非常令人信服的理由这样做,否则我会回到单个UI线程。

假设您必须拥有多个UI线程,黄金法则是控件只能从创建它们的UI线程更新。。如果您想通常调用方法,则根本不需要编组它们。但是,如果这些方法又与UI控件交互,那么您只需调用该调用,就像调用来自任何其他不属于控件的UI线程的其他线程一样

如果你有类似

的话
btnOnForm1OnUIThread1_Click(...)
{
    UpdateForm2OnUIThread2();
}

UpdateForm2OnUIThread2()
{
    if (control.InvokeRequired)
    {
      // Syntax of this line may be slightly off as I'm writing from memory ... 
      // I normally use an extension method
      control.Invoke(UpdateForm2OnUIThread2); 
    }
    else
    {
      control.Text = "Blah";
    }    
}

答案 1 :(得分:0)

一个。如果你知道你做了什么,使用多个UI线程没有任何问题。

湾调用UI线程工作者是错误和混乱的 - UI线程#2与#1相同 从开发人员的角度来看。一旦你意识到这一点 - 很多问题都会自行解决。

℃。如果你想从view1 [在UI线程#1中运行]调用view2.SomeMethod()[在UI线程#2中运行] - 在view2上调用BeginInvoke。

以下代码很容易采用。 button1 - 启动第二个UI线程。 button2 - 从UI线程2中的表单上的UI线程1调用方法

    Form2 form;
    private void button1_Click(object sender, EventArgs e)
    {
        Thread viewThread = new Thread(() =>
        {
            form = new Form2();
            Application.Run(form);
        });
        viewThread.SetApartmentState(ApartmentState.STA);
        viewThread.Start();

        label1.Text = Thread.CurrentThread.ManagedThreadId.ToString();

    }

    private void button2_Click(object sender, EventArgs e)
    {
        if (form != null)
        {
            form.BeginInvoke(new Action(() => 
                {form.Method("Form1 is calling...");}));
        }
    }

形式为2:

    public void Method(string s)
    {
        label1.Text = string.Format("{0} '{1}'", 
                        Thread.CurrentThread.ManagedThreadId, s);
    }

您将看到线程编号不同但字符串已越过它们。