调用冻结我的Windows窗体

时间:2015-12-21 18:46:20

标签: c# multithreading winforms invoke begininvoke

我正在尝试做我的第一个多线程窗口表单应用程序,我有一个重要的问题。 我知道我必须在我的线程中使用Invoke或BeginInvoke在我的表单中更改RichTextBox,但是当我尝试执行此操作时,我的UI才会冻结,而控制台正在正确打印我的结果。

     class MyThread
    {
        public MyThread()
        {

        }


        public void Run()
        {
            byte[] tmp;
            while (true)
            {

                // lock (sem1)
                Monitor.Enter(sem1);
                {
                    if (end)
                    {
                        Monitor.Exit(sem1);
                        break;
                    }
                        tmp = inp.ReadNr();

                    if (inp.End())
                        end = true;
                }
                if(inOrder)
                Monitor.Enter(sem2);
                Monitor.Exit(sem1);

                bool p = CSL.checkNr((byte[])tmp.Clone());
                Monitor.Enter(sem3);
                if(inOrder)
                Monitor.Exit(sem2);
                {
                    outp.WriteNr(tmp, p);
                    //win.richTextBox2.AppendText(String.Join("", tmp) + '\n');
                    win.richTextBox2.BeginInvoke(new Action(delegate ()
                    {
                        win.richTextBox2.AppendText("wtf");
                    }));
                }
                Monitor.Exit(sem3);

            }
        }
    }

“win”是我的Form1类的对象。我不能处理它......

编辑:

    static public void loading()
    {
        outp = new oFile();
        Thread[] thr = new Thread[nrThreads];
        for (int a = 0; a < nrThreads; a++)
            new Thread(new ThreadStart(new MyThread().Run)).Start();
        //new MyThread().Run();
        Console.ReadKey();
    }

形式:

private void button1_Click(object sender, EventArgs e)
    {
        Program.loading();
    }

1 个答案:

答案 0 :(得分:3)

这里的问题是Program.loading中的这一行:

Console.ReadKey();

这会停止其轨道中的主GUI线程,所以让我们看看现在发生了什么:

  1. 发布到主GUI线程的消息不会被处理(因为您没有返回消息循环)
  2. 来自不同线程的BeginInvoke不会被处理,因为它们通过将消息发布到主GUI线程正在处理的相同消息队列(现在已暂停)来工作。
  3. 直到你按一个键(假设这是可能的),一切都会停止。您会注意到,对表单的绘制消息不会得到处理,最终表单会逐渐消失并且已经停止响应&#34;已经停止响应&#34;文本。
  4. 所以删除那行代码,至少你的程序不应该像以前一样停在它的轨道上。

    话虽如此,我建议你先尝试一些简单的例子。您对多个监视器的交错,手动和处理让我觉得您刚开始学习多线程编程,并且已经开始使用一些需要非常准确地互锁才能正常工作的复杂齿轮。

    相反,我会要求您查看async / await,在C#5中添加的新关键字来处理异步编程。虽然异步和多线程不是同一个东西,也不暗示另一个,但是异步编程通常会让你走向一个在等待事物时不会冻结的响应式用户界面。