在while()循环中使用ManualResetEvent()

时间:2016-09-30 10:01:04

标签: c# multithreading thread-safety

我对我的简单代码有疑问:

 public partial class Form1 : Form {

  ManualResetEvent ResetEvt = new ManualResetEvent(false);
  Thread t1;
  public Form1() {
     InitializeComponent();
  }
  //create
  private void button1_Click(object sender, EventArgs e) {
     t1 = new Thread(new ParameterizedThreadStart((reset) => {
        int cont = 0;
        var resett = reset as ManualResetEvent;
        Thread.CurrentThread.IsBackground = true;
        while (resett.WaitOne()) {
           try {
              this.BeginInvoke(new Action(() => this.richTextBox1.AppendText("Ciao " + cont)));
              cont++;
              Thread.Sleep(500);
           }
           catch (Exception) {
              MessageBox.Show("END");
           }
        }
        this.BeginInvoke(new Action(() => this.richTextBox1.AppendText("ok finished " + cont)));
     }));
  }

  private void button2_Click(object sender, EventArgs e) {

     try {
        t1.Start(this.ResetEvt);
     }
     catch (Exception) {

     }
  }

  private void button3_Click(object sender, EventArgs e) {
     this.ResetEvt.Reset();
  }

  private void button4_Click(object sender, EventArgs e) {
     ResetEvt.Set();
  }

  private void button5_Click(object sender, EventArgs e) {
     // ??? ho can stop while? and continue execution?
  }

}

Weel,如何使用ManualResetEvent既清晰又简单,但为什么要行  this.BeginInvoke(new Action(() => this.richTextBox1.AppendText("ok finished " + cont)));永远不会被执行?我可以停止我的线程(.Reset)并重新启动它(.Set),但是当resett.WaitOne()变为FALSE时为什么我的代码不会跳转到this.BeginInvoke(new Action(() => this.richTextBox1.AppendText("ok finished " + cont)));

非常感谢。

2 个答案:

答案 0 :(得分:1)

我不确定我是否可以通过您的代码查看您想要的内容,但您可以执行以下操作:

while (!resett.WaitOne(500))
{
}

然后有第三个按钮来停止循环:

private void button3_Click(object sender, EventArgs e)
{
  ResetEvt.Set();
}

不带参数的WaitOne()会阻塞当前线程,直到我设置的处理程序,但是在该时间之后返回的参数以毫秒为单位,但只要处理程序未设置就为false。

答案 1 :(得分:0)

ManualResetEvent.WaitOne() 永远不会返回false。阅读documentation

ManualResetEvent是一个简单的信令原语。它只有两个逻辑值 - 设置,而不是设置。当您WaitOne对未设置的事件进行处理时,它将一直阻止,直到设置了该事件。就是这样 - WaitOne不返回表示事件状态的布尔值 - 它只会在事件设置时返回。

返回值用于超时的重载。在这种情况下,WaitOne将在超时到期时返回false,如果事件在此期间发出信号,则返回true。

多线程很难 - 你不想猜测。我强烈建议至少通过多线程的介绍性文本 - http://www.albahari.com/threading/是一个很好的免费资源,可以提供很好的解释,让你最好的方式来至少理解你将要成为的问题面对。

在你的情况下,你真正想要的是Timer。或者更好的是,如果您正在等待某个异步事件发生,请使用异步代码 - 这样可以避免所有繁忙的循环,以及无意义的Thread

您的代码还存在其他问题。您可能希望将(工作)代码带到CodeReview以获取一些指示。