Wednesday, February 19, 2014

How to use threading with buffer (with correct way of terminating the thread)?

using System.Threading;

namespace Form1
{
    public partial class Form1: Form
    {

        //Threading
        private Thread processorThread = null;
        private readonly object _locker = new object();
        private volatile bool _shouldStop = false; //To exit thread cleanly
        private Queue<int> buffer = new Queue<int>();


        public Form1(Form callingForm, int formNum)
        {
              processorThread= new Thread(processNumber);
              processorThread.IsBackground = true; //Thread will terminate automatically when program close
              processorThread.Start();
         }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _shouldStop = true;
            processorThread.Interrupt();
            processorThread.Join(3000);
         }

        private void processNumber()
        {
            int myNumber;

            while (!_shouldStop)
            {
                try
                {
                    lock (_locker)
                    {
                        if (buffer.Count == 0)
                            Monitor.Wait(_locker); //Releases the lock on an object and blocks the current thread until it reacquires the lock.
                    }
                    lock (_locker)
                    {
                        myNumber= buffer.Dequeue();
                    }

                    tsDictionary = displayNumber(myNumber);
                }
                catch (Exception err)
                {
                    //MessageBox.Show(this, "processNumber(): " + err.Message);
                }
            }
        }

        private void number_Update(object sender, EventArgs e) //an imaginary event that send a random number on random time
        {          
            try
            {
                if (e != null)
                {
                    lock (_locker)
                    {
                        buffer.Enqueue(e.number);
                        Monitor.Pulse(_locker); //Notifies a thread in the waiting queue of a change in the locked object's state - i.e. "wake" the waiting thread
                    }
                }
            }
            catch (Exception err)
            {
            }

        }

        void displayNumber(int number)
        {
            if (label1.InvokeRequired)
            {
                MethodInvoker invoker = () => displayNumber(number);
                label1.Invoke(invoker);
            }
            else
                label1.Text += " " + number.ToString();
         }
     }
}
     

No comments:

Post a Comment