Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 调用冻结我的Windows窗体_C#_Multithreading_Winforms_Invoke_Begininvoke - Fatal编程技术网

C# 调用冻结我的Windows窗体

C# 调用冻结我的Windows窗体,c#,multithreading,winforms,invoke,begininvoke,C#,Multithreading,Winforms,Invoke,Begininvoke,我正在尝试我的第一个多线程windows窗体应用程序,我有一个重要的问题。 我知道我必须在我的线程中使用Invoke或BeginInvoke来更改表单中的RichTextBox,但当我尝试这样做时,UI只是冻结了,而控制台正在正确打印我的结果 class MyThread { public MyThread() { } public void Run() { byte[

我正在尝试我的第一个多线程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);

            }
        }
    }
“赢”是我班的目标。我不能处理它

编辑:


这里的问题是
程序中的这一行。正在加载

Console.ReadKey();
这将停止主GUI线程的运行,让我们看看现在会发生什么:

  • 发布到主GUI线程的消息不会得到处理(因为您不会返回到消息循环)
  • 来自不同线程的BeginInvoke不会得到处理,因为它们通过将消息发布到主GUI线程正在处理的同一消息队列(现在已停止)来工作
  • 直到你按下一个键(假设这是可能的),一切都会停止。您会注意到,将消息绘制到表单不会得到处理,最终表单将淡出并获得“已停止响应”文本
  • 所以,删除这行代码,至少你的程序不应该像以前那样死气沉沉


    话虽如此,我敦促你们首先尝试更简单的例子。您对多个监视器的交叉、手动处理让我觉得您刚刚开始学习多线程编程,并且已经开始学习一些复杂的齿轮,这些齿轮需要非常精确地联锁才能正常工作


    相反,我想让您看看
    async/await
    ,这是在C#5中添加的用于处理异步编程的新关键字。虽然异步和多线程不是一回事,也不是二者都意味着另一回事,但异步编程通常会让您在等待时不会冻结响应UI。

    是在后台线程还是UI线程上运行
    Run
    方法?作为旁注,使用
    Monitor.Enter
    Monitor.Exit
    而不是
    lock
    语句是不寻常的,除非你真的知道自己在做什么,否则可能是个坏主意。例如,如果在
    Enter
    Exit
    之间的代码抛出异常,则对象将保持锁定状态。@adv12我刚刚编辑了我的文章,我是如何运行线程的。UI线程正在运行创建和启动线程的方法。Program.loading()
    做什么?基本上,您所做的是停止为拥有表单的线程处理消息的消息循环。BeginInvoke的工作原理是将消息发布到该线程,该线程最终由该消息循环处理。当您使用Console.ReadKey时,一切都停止了工作,与线程或begininvoke无关,尽管它们是同一问题的受害者。此外,您还应该将async/await视为完全多线程编程的替代方案,它有些不同,也有些简单。
    private void button1_Click(object sender, EventArgs e)
        {
            Program.loading();
        }
    
    Console.ReadKey();