ManualResetEvent奇怪的行为

时间:2016-06-02 18:25:47

标签: c# multithreading winforms

在询问之前,我将首先展示一些代码......

public partial class Player : UserControl
{
    ManualResetEvent _pauseEvent;
    ManualResetEvent _stopEvent;

    Thread t;

    public Player()
    {
        InitializeComponent();

        this.Disposed += (s, a) =>
        {
            Quit();
        };

        _pauseEvent = new ManualResetEvent(true);
        _stopEvent = new ManualResetEvent(false);

        // Creates the thread...
        t = new Thread(StartText);
        t.IsBackground = false;

        // Starts with thread paused...
        StopPlaying();

        // Let's go!
        t.Start();
    }

    public void StopPlaying()
    {
        Console.WriteLine("Ordered to stop");
        _pauseEvent.Reset();
    }

    private void ResumePlaying()
    {
        Console.WriteLine("Ordered to resume");
        _pauseEvent.Set();
    }

    public void Quit()
    {
        _pauseEvent.Set();
        _stopEvent.Set();
    }

    public void SetText(string text, bool loop)
    {
        StopPlaying();

        // Here we supose the thread would be stopped!!!! But it's not!!!
        // But when I call StopPlaying() from a button on the form that
        //   contains this usercontrol, everything works as expected

        ...... Do some processing here .....

        ResumePlaying();
    }

    private void StartText()
    {
        while (true)
        {
            _pauseEvent.WaitOne(Timeout.Infinite);

            if (_stopEvent.WaitOne(0))
                break;

                do // While LOOP
                {
                        ... Do some process here .....

                        // Verifies if stop requested
                        if (!_pauseEvent.WaitOne(0))
                        {
                            Console.WriteLine("STOP REQUESTED");
                            break;
                        }
                    }

                } while (LOOP);
            }
    }
}

我的问题是:

当我从包含此UserControl的窗体的按钮调用StopPlaying()时,在线程内部进行的测试会正确检测到,但是当我从SetText()方法调用StopPlaying时,它不起作用,就像事件一样没有重置。

顺便说一句,方法SetText()由另一个相同形式的按钮调用。

1 个答案:

答案 0 :(得分:2)

您的StartText()方法看起来有竞争条件。您已在单独的线程上运行StartText,并且从主UI线程调用SetText(),因此可能发生的事情是SetText()正在重置然后设置_pauseEvent在将控制权传递回另一个线程之前。因此,就StartText而言,重置永远不会发生。