Click here to Skip to main content
15,896,063 members
Articles / Programming Languages / C#

Using events for thread synchronization

Rate me:
Please Sign up or sign in to vote.
4.74/5 (35 votes)
27 Mar 2002CPOL5 min read 378.5K   2K   67  
An introduction to using signaled events for thread synchronization in .NET
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;

namespace ThreadSync01
{
    // For .NET 2.0 support
    public delegate void Action();

	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{
		private System.Windows.Forms.ListBox listBox1;
		private System.Windows.Forms.Button button1;
		private System.Windows.Forms.Button button2;
		private System.Windows.Forms.Button button3;
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			m_mre = new ManualResetEvent(false);
			m_mreB = new ManualResetEvent(false);
			m_mre_array = new ManualResetEvent[2];
			m_mre_array[0]=m_mre;
			m_mre_array[1]=m_mreB;

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			try
			{
				base.Dispose( disposing );
			}
			catch
			{
				//I had to do this cause this kept raising exceptions.
				//The reason was that the threads were still active.
				//The solution in a real life situation would be use 
				//an event here to wait till all threads are finished.
				//Ironic that an example program for a thread sync
				//mechanism does not use any thread sync --- Nish
			}
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.listBox1 = new System.Windows.Forms.ListBox();
			this.button1 = new System.Windows.Forms.Button();
			this.button2 = new System.Windows.Forms.Button();
			this.button3 = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// listBox1
			// 
			this.listBox1.Location = new System.Drawing.Point(16, 16);
			this.listBox1.Name = "listBox1";
			this.listBox1.Size = new System.Drawing.Size(272, 212);
			this.listBox1.TabIndex = 0;
			// 
			// button1
			// 
			this.button1.Location = new System.Drawing.Point(16, 248);
			this.button1.Name = "button1";
			this.button1.Size = new System.Drawing.Size(72, 24);
			this.button1.TabIndex = 1;
			this.button1.Text = "Try1";
			this.button1.Click += new System.EventHandler(this.button1_Click);
			// 
			// button2
			// 
			this.button2.Location = new System.Drawing.Point(112, 248);
			this.button2.Name = "button2";
			this.button2.Size = new System.Drawing.Size(72, 24);
			this.button2.TabIndex = 2;
			this.button2.Text = "Try2";
			this.button2.Click += new System.EventHandler(this.button2_Click);
			// 
			// button3
			// 
			this.button3.Location = new System.Drawing.Point(216, 248);
			this.button3.Name = "button3";
			this.button3.Size = new System.Drawing.Size(72, 24);
			this.button3.TabIndex = 3;
			this.button3.Text = "Try3";
			this.button3.Click += new System.EventHandler(this.button3_Click);
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(306, 288);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.button3,
																		  this.button2,
																		  this.button1,
																		  this.listBox1});
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
			this.Name = "Form1";
			this.Text = "ThreadSync01";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[MTAThread]
		static void Main() 
		{
			try
			{
				Application.Run(new Form1());
			}
			catch
			{
				//same explanation as in Dispose(...) - Nish
			}
		}

		public int m_x=0;

		public void ReadThread10()
		{
			int a = 10;
			for(int y=0;y<5;y++)
			{
				string s = "ReadThread10";
				s = s + " # multiplier= ";
				s = s + Convert.ToString(a) + " # ";
				s = s + a * m_x;
                listBox1.BeginInvoke((Action)(() => listBox1.Items.Add(s)));
				Thread.Sleep(1000);
			}
		}

		public void ReadThread20()
		{
			int a = 20;
			for(int y=0;y<5;y++)
			{
				string s = "ReadThread20";
				s = s + " # multiplier= ";
				s = s + Convert.ToString(a) + " # ";
				s = s + a * m_x;
                listBox1.BeginInvoke((Action)(() => listBox1.Items.Add(s)));
				Thread.Sleep(1000);
			}
		}

		public void WriteThread()
		{
			Thread.Sleep(1000);
			m_x=3;
		}		

		public void SafeWriteThread()
		{
			m_mre.Reset();
			WriteThread();
			m_mre.Set();
		}

		public void SafeWriteThreadB()
		{	
			m_mreB.Reset();
			m_mre.WaitOne();
			Thread.Sleep(1000);
			m_x+=3;			
			m_mreB.Set();
		}

		public void SafeReadThread10()
		{
			m_mre.WaitOne();
			ReadThread10();
		}

		public void SafeReadThread20()
		{
			m_mre.WaitOne();
			ReadThread20();
		}

		public void SafeReadThread10B()
		{
			WaitHandle.WaitAll(m_mre_array);
			ReadThread10();
		}

		public void SafeReadThread20B()
		{
			WaitHandle.WaitAll(m_mre_array);
			ReadThread20();
		}

		private void button1_Click(object sender, System.EventArgs e)
		{
			listBox1.Items.Clear();
			listBox1.Items.Add("No sync mechanism used");
			listBox1.Items.Add("");
			Thread t0 = new Thread(new ThreadStart(WriteThread));
			Thread t1 = new Thread(new ThreadStart(ReadThread10));
			Thread t2 = new Thread(new ThreadStart(ReadThread20));
			t0.IsBackground=true;
			t1.IsBackground=true;
			t2.IsBackground=true;
			t0.Start();
			t1.Start();
			t2.Start();
		}

		private void button2_Click(object sender, System.EventArgs e)
		{
			listBox1.Items.Clear();
			listBox1.Items.Add("One Write thread - Multiple Read threads");
			listBox1.Items.Add("");
			Thread t0 = new Thread(new ThreadStart(SafeWriteThread));
			Thread t1 = new Thread(new ThreadStart(SafeReadThread10));
			Thread t2 = new Thread(new ThreadStart(SafeReadThread20));
			t0.IsBackground=true;
			t1.IsBackground=true;
			t2.IsBackground=true;
			t0.Start();
			t1.Start();
			t2.Start();
		}

		public ManualResetEvent m_mre;
		public ManualResetEvent m_mreB;
		public ManualResetEvent[] m_mre_array;

		private void button3_Click(object sender, System.EventArgs e)
		{
			listBox1.Items.Clear();
			listBox1.Items.Add("Multiple Write threads - Multiple Read threads");
			listBox1.Items.Add("");
			Thread t0 = new Thread(new ThreadStart(SafeWriteThread));
			Thread t0B = new Thread(new ThreadStart(SafeWriteThreadB));
			Thread t1 = new Thread(new ThreadStart(SafeReadThread10B));
			Thread t2 = new Thread(new ThreadStart(SafeReadThread20B));
			t0.IsBackground=true;
			t0B.IsBackground=true;
			t1.IsBackground=true;
			t2.IsBackground=true;
			t0.Start();
			t0B.Start();
			t1.Start();
			t2.Start();
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Nish Nishant is a technology enthusiast from Columbus, Ohio. He has over 20 years of software industry experience in various roles including Chief Technology Officer, Senior Solution Architect, Lead Software Architect, Principal Software Engineer, and Engineering/Architecture Team Leader. Nish is a 14-time recipient of the Microsoft Visual C++ MVP Award.

Nish authored C++/CLI in Action for Manning Publications in 2005, and co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his WordPress blog. Nish is experienced in technology leadership, solution architecture, software architecture, cloud development (AWS and Azure), REST services, software engineering best practices, CI/CD, mentoring, and directing all stages of software development.

Nish's Technology Blog : voidnish.wordpress.com

Comments and Discussions