Nilo Paim
Nilo Paim

Reputation: 447

ManualResetEvent strange behaviour

Before asking, I'll first show some code...

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);
            }
    }
}

My problem is:

When I call StopPlaying() from a button of the form that contains this UserControl, the test made inside the thread detects correctly, but when I call StopPlaying from the SetText() method it doesn't work, as if the event is not resetted.

By the way, the method SetText() is called by another button of the same form.

Upvotes: 0

Views: 107

Answers (1)

Lee Painton
Lee Painton

Reputation: 62

It looks like you have a race condition in your StartText() method. You have StartText running on a separate thread and SetText() is called from the main UI thread, so what's probably happening is that SetText() is resetting and then setting _pauseEvent before control is passed back to the other thread. So as far as StartText is concerned the reset never happens.

Upvotes: 2

Related Questions