C# 从UI线程调用工作线程上的方法

C# 从UI线程调用工作线程上的方法,c#,winforms,multithreading,C#,Winforms,Multithreading,在Winforms中使用C#,我有一个主窗体,可以在单独的线程上创建第二个UI窗体 viewThread = new Thread( ( ) => { views = new Views.Views( displayRotators, screenLocationLeft, screenLocationTop, screenHeight, screenWidth ); Application.Run( views ); } ); viewThread.SetApartmentS

在Winforms中使用C#,我有一个主窗体,可以在单独的线程上创建第二个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线程调用工作线程上的方法。谁能告诉我怎么做


谢谢。

只有极少数情况下运行多个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";
    }    
}

很少有情况下运行多个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";
    }    
}

a。如果您知道自己在做什么,那么使用多个UI线程没有什么错

b。调用UI线程工作程序是不正确和混乱的-UI线程#2与#1相同 从开发者的立场来看。一旦你意识到这一点,许多问题就会自行解决

c。如果要从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);
    }

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

a。如果您知道自己在做什么,那么使用多个UI线程没有什么错

b。调用UI线程工作程序是不正确和混乱的-UI线程#2与#1相同 从开发者的立场来看。一旦你意识到这一点,许多问题就会自行解决

c。如果要从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);
    }

您将看到线程编号不同,但字符串已穿过它们。请不要为自己创建多个UI线程。您最好始终只使用一个线程。您不能从主线程以外的任何线程修改UI,因此无法执行您的要求。为了您自己的缘故,请不要创建多个UI线程。您最好始终只使用一个线程。您不能从主线程以外的任何线程修改UI,因此无法执行您的要求。好吧,是和否。第二个表单(工作线程)上的方法基本上会永远循环(直到停止),只需一个接一个地公开一系列GroupBox。我试图直接调用“Start”方法,但是由于我启动第二个表单的方式,我得到的是NULL,而不是对表单的引用。我想我遗漏了一些东西。在我提供的原始代码片段中,当我从新的线程函数中出来时,“views”为NULL。我本来希望得到表单的句柄,但我没有,所以我不能像我需要的那样简单地调用views.Start()。好吧,是和否。第二个表单(工作线程)上的方法基本上会永远循环(直到停止),只需一个接一个地公开一系列GroupBox。我试图直接调用“Start”方法,但是由于我启动第二个表单的方式,我得到的是NULL,而不是对表单的引用。我想我遗漏了一些东西。在我提供的原始代码片段中,当我从新的线程函数中出来时,“views”为NULL。我本来希望得到表单的句柄,但我没有,所以我不能像我需要的那样简单地调用views.Start()。