2015-12-21 96 views
1

我正在尝试执行我的第一个多线程窗体表单应用程序,并且我有1个重要问题。 我知道我必须在我的线程中使用Invoke或BeginInvoke来更改我的表单中的RichTextBox,但是当我尝试这样做时,我的UI只是冻结,而控制台正确打印我的结果。调用冻结我的Windows窗体

 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(); 
    } 
+0

“Run”方法是在后台线程还是UI线程上运行? – adv12

+3

作为一个方面说明,直接使用'Monitor.Enter'和'Monitor.Exit'而不是'lock'语句是不寻常的,可能是一个坏主意,除非你真的知道你在做什么。例如,如果你在'Enter'和'Exit'之间的代码引发一个异常,那么该对象将保持锁定状态。 – adv12

+0

@ adv12我刚刚编辑我的帖子如何运行我的线程。 UI线程正在运行创建和启动我的线程的方法。 –

回答

3

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

Console.ReadKey(); 

这将停止在它的轨道中的主要GUI线程,让我们看看现在会发生什么:

  1. 消息张贴到主界面线程不会得到处理来自不同的线程(因为你没有返回回消息循环)
  2. 的BeginInvoke不会得到处理,因为他们通过发布信息工作到主GUI线程正在处理的同一个消息队列(现在已经停止)
  3. 直到你按下一个键(假设这是可能的),一切都会停止。您会注意到,表单的绘制消息不会得到处理,最终表单将淡出并获取“已停止响应”文本。

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


话虽如此,我敦促您尝试更简单的例子开始。您对多个显示器进行交错处理,手动处理让我觉得您刚刚开始学习多线程编程,并开始使用一些需要非常准确地互锁才能正确工作的复杂齿轮。

相反,我会请你看看async/await,在C#5中添加新的关键字来处理异步编程。虽然异步和多线程不是同一件事,但也不意味着另一个意思,异步编程通常可以让您以大部分的方式实现响应式用户界面,而这些用户界面在等待事件时不会冻结。