【问题标题】:Call method on worker thread FROM the UI thread从 UI 线程调用工作线程上的方法
【发布时间】:2013-01-31 12:12:18
【问题描述】:

使用 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 线程调用工作线程上的方法。谁能告诉我该怎么做?

谢谢。

【问题讨论】:

  • 为了您自己,请不要创建多个 UI 线程。始终拥有一个会更好。
  • 您不能从除主线程之外的任何线程修改 UI,因此无法按照您的要求进行操作。

标签: c# winforms multithreading


【解决方案1】:

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

【讨论】:

  • 嗯,是的,也不是。第二种形式(工作线程)上的方法基本上将永远循环(直到停止),并且简单地一个接一个地公开一系列 GroupBox。我尝试直接调用“Start”方法,但由于我启动第二个表单的方式,我得到的是 NULL 而不是对表单的引用。
  • 我想我错过了一些东西。在我提出的原始代码 sn-p 中,当我退出新的 Thread 函数时,'views' 为 NULL。我本来希望得到表单的句柄,但我没有,所以我不能像我需要的那样简单地调用views.Start()。
【解决方案2】:

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

b.调用 UI 线程工作者是不正确且令人困惑的 - UI 线程 #2 与 #1 相同 从开发者的角度来看。一旦你意识到这一点 - 许多问题都会自行解决。

c。如果您想从 view1 [在 UI 线程 #1 中运行] 调用 view2.SomeMethod() [在 UI 线程 #2 中运行] - 在 vi​​ew2 上调用 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);
    }

你会看到线程号不同,但字符串已经越过了它们。

【讨论】:

    猜你喜欢
    • 2012-01-24
    • 2012-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多