调用冻结我的Windows窗体

本文关键字:窗体 Windows 我的 冻结 调用 | 更新日期: 2023-09-27 18:27:42

我正在尝试我的第一个多线程windows表单应用程序,但我遇到了一个重要问题。我知道我必须在线程中使用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);
            }
        }
    }

"胜利"是我班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();
    }

调用冻结我的Windows窗体

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

Console.ReadKey();

这会使主GUI线程停止运行,所以让我们看看现在发生了什么:

  1. 发布到主GUI线程的消息将不会得到处理(因为您不会返回到消息循环)
  2. 来自不同线程的BeginInvoke不会被处理,因为它们的工作方式是将消息发布到主GUI线程正在处理的同一消息队列(现在已经停止)
  3. 直到你按下一个键(假设这是可能的),一切都会停止。您会注意到,表单中的绘画消息不会得到处理,最终表单会淡出并显示"已停止响应"文本

因此,删除这行代码,至少你的程序不应该像以前那样停滞不前。


话虽如此,我敦促你从一开始就尝试更简单的例子。您对多个监视器的交错、手动处理让我认为您正处于学习多线程编程的初级阶段,并且已经开始使用一些复杂的齿轮,这些齿轮需要非常准确地互锁才能正确工作。

相反,我想让您看看async / await,它是在C#5中添加的用于处理异步编程的新关键字。尽管异步和多线程不是一回事,也不意味着两者都是另一回事,但异步编程通常会让你在很大程度上获得一个响应UI,它不会在等待时冻结。