Click here to Skip to main content
Click here to Skip to main content

Threading in C#

, , 21 May 2001
Rate this:
Please Sign up or sign in to vote.
This application demonstrates the threads in C# using Forms and GUI controls.
<!-- Download Links -->

Introduction

A thread is a sequence of instructions executed within the context of a process. MultiThreading is achieved when a  program uses multiple execution threads allowing each thread to share the CPU concurrently depending on the priority assigned to these threads. This helps in the optimum usage of System Resources.

Our application shows how multiple threads (in our case two) run on different level of priorities. We will discuss the whole program part by part.

Code Analysis

//Import These System NameSpaces 
 
       using System;       
       using System.Drawing;
       using System.WinForms;
       using System.Threading;

We make use of the above mentioned NameSpaces for our application.

System.WinForms and System.Drawing are used to handle the Graphical User Interface. The Progress Bar and Buttons we make all come under and all come as a part of the System.WinForms namespace.

By System.Drawing we take care of all the positioning and size of the WinForm controls. Point and Size are the built-in objects supported by the Drawing namespace.

The System.Threading namespace provides classes and interfaces that enable multi-threaded programming. This namespace includes a ThreadPool class that manages groups of threads, a Timer class that enables a delegate to be called after a specified amount of time, and a Mutex class for synchronizing mutually-exclusive threads. I also provides classes for thread scheduling, wait notification, and deadlock resolution.

//Declarations

public class PgBar : Form
{
    static int tp1, tp2;
    Thread thread , td;
    ProgressBar pg1 = new ProgressBar();
    ProgressBar pg2 = new ProgressBar();
    Button bt = new Button();
    Button bt1 = new Button();
    Button bt2 = new Button();

This is the declaration part of the Application. Here we are basically declaring public variables and objects. We declare two threads using the Thread class and the other control functions like Progress Bar, ComboBox and Buttons.

    static ComboBox cb1 = new ComboBox();
    ComboBox.ObjectCollection c1 = new ComboBox.ObjectCollection(cb1);
 
    static ComboBox cb2 = new ComboBox();
    ComboBox.ObjectCollection c2 = new ComboBox.ObjectCollection(cb2);

Note that the ComboBox declaration is different from those that you observe in ProgressBar and Button. This is because the statement

    static ComboBox cb1 = new ComboBox();

just creates an instance of the ComboBox, and if you want to add items to this you will have to declare an ComboBox.ObjectCollection object.

    ComboBox.ObjectCollection c1 = new ComboBox.ObjectCollection(cb1);

 The ComboBox.ObjectCollection constructor takes in a ComboBox object, which becomes the owner of the ObjectCollection. Now for inserting items into the ComboBox you will have to insert the items in the ObjectCollection. For Example:

    c1.Insert(0,"Lowest");

This is the Main function for the application. It creates an instance of this class that is PgBar. And the second statement runs the application.

//Main
 
public static void Main()
{
    PgBar pgbApp = new PgBar();
    Application.Run(pgbApp);
}
    
//Constructor
 
public PgBar()
{
    this.Text = "THE THREADER-> NARENDAR AND ANSHUMAN";
    this.Size = new Size(500,200);
    this.BackColor = Color.Black;
    this.ForeColor = Color.White;
 
    pg1.Maximum = 300;
    pg1.Minimum = 0;
    pg1.Step = 20;
    pg1.Location = new Point(10,10);
    pg1.Size = new Size(300,20);
    pg1.BackColor = Color.White;
    pg1.ForeColor = Color.Gray;
 
    pg2.Maximum = 300;
    pg2.Minimum = 0;
    pg2.Step = 20;
    pg2.Location = new Point(10,40);
    pg2.Size = new Size(300,20);
    pg2.BackColor = Color.White;
    pg2.ForeColor = Color.Gray;
 
    bt.Text = "START";
    bt.Location = new Point(40,80);
    bt.Size = new Size(60,20);
 
    bt1.Text = "CLEAR";
    bt1.Location = new Point(120,80);
    bt1.Size = new Size(60,20);
 
    bt2.Text = "EXIT";
    bt2.Location = new Point(200,80);
    bt2.Size = new Size(60,20);
 
    c1.Insert(0,"Lowest");
    c1.Insert(1,"Below Normal Lowest");
    c1.Insert(2,"Normal");
    c1.Insert(3,"Above Normal");
    c1.Insert(4,"Highest");
 
    cb1.SelectedIndex = 0;
    cb1.Location = new Point(320,10);
    
    c2.Insert(0,"Lowest");
    c2.Insert(1,"Below Normal");
    c2.Insert(2,"Normal");
    c2.Insert(3,"Above Normal");
    c2.Insert(4,"Highest");
 
    cb2.SelectedIndex = 0;
    cb2.Location = new Point(320,40);
 
    this.Controls.Add(bt);
    this.Controls.Add(bt1);
    this.Controls.Add(bt2);
    this.Controls.Add(pg1);
    this.Controls.Add(pg2);
    this.Controls.Add(cb1);
    this.Controls.Add(cb2);

The above block of code defines all the Graphical Controls. We create the controls by giving definitions to all the controls declared during the declaration stage.

    this.Controls.Add(bt);

The above statement adds the Button bt to the Form. The keyword this here corresponds to the present Form.

    //Event Delegation

    bt.Click+= new EventHandler(this.timer1_Tick);
    bt1.Click+= new EventHandler(this.timer1_Tick);
    bt2.Click+= new EventHandler(this.timer1_Tick);

These statements basically define the event handling method for the buttons in the form. When you create an EventHandler delegate, you specify the method that will handle the event, which in our case is - timer1_Tick. Once the delegate is assigned to the event, the handler method is automatically invoked whenever the event is triggered. So once you click any of the buttons the method time1_Tick is invoked.

//timer1_Tick Method : EventHandling Method

The syntax of the EventHandler delegate specifies the signature for the event handler, where sender is the source of the event and e is an Event object. So the EventHandler method timer1_Tick takes in the source that is the object that triggers the method and an event object. The timer1_Tick method's access modifier is protected and it returns void, that is, nothing.

protected void timer1_Tick (object sender, System.EventArgs e)

If the Button bt, which corresponds to Start in the application, is clicked this block of code will get executed.

    if(sender==bt)
    {
        pg1.Value = 0;
        pg2.Value = 0;
 
        tp1 = cb1.SelectedIndex;
        tp2 = cb2.SelectedIndex;
 
        thread = new Thread(new ThreadStart(Display));
        place(ref thread,tp1);
        thread.Start();
 
        td = new Thread(new ThreadStart(Displaytd));
        place(ref td,tp2);
        td.Start();
    }

pg1 is an instance of ProgressBar, and pg1.Value is the property of ProgressBar that assigns or gets the value of the current position the ProgressBar. cb1 is an instance of ComboBox, and SelectedIndex indicates the [zero based] index of the currently selected item in the combos list. The application runs the two ProgressBars as two threads and the two ComboBox allows the user to set the priorities at runtime for these ProgressBars. We create instances for two threads - thread and td. The constructor of Thread class takes instance of  a ThreadStart class. The ThreadStart class is a delegate that points to the method that should be executed first when a thread is started. thread invokes Display method and td invokes Displaytd.  The selected value in ComboBox is captured in a static int variables tp1 and tp2. We pass the reference of the threads and the corresponding index value to method place(). place() method will be explained later. <threadobject>.start() starts executing the thread.

    if(sender==bt1)
    {
        pg1.Value=0;
        pg2.Value=0;
    }

If the Button bt1, which corresponds to Clear in the application, is clicked this block of code will get executed. It just assigns the values to both the ProgressBar instances as 0, thereby, clearing both the ProgressBar.

    if(sender==bt2)
    {
        Application.Exit();
        if(td.IsAlive)
             td.Abort();
        if(thread.IsAlive)
             thread.Abort();
    }

If the Button bt2, which corresponds to Exit in the application, is clicked this block of code will get executed. <threadobject>.IsAlive returns true or false depending on whether the Thread is running or not.  This checking is must as otherwise it throws ThreadStateException. <threadobject>.Abort() method exits the thread. The Application is closed and both the threads (if they are alive) are aborted.

    //ThreadStart Invoked Methods

    protected void Display()
    {
        for(long i = 0l; i<20000000; i++)
        {
            if(i%1000000 == 0)
            {
                if(pg1.Value != 300)
                    pg1.Value += 20;
                else
                    thread.Abort();
            }
        }
 
    }
 
    protected void Displaytd()
    {
        for(long i = 0l; i<20000000; i++)
        {
            if(i%1000000 == 0)
            {
                if(pg2.Value != 300)
                    pg2.Value += 20;
                else
                    td.Abort();
            }
        }
    }

Both Display() and Displaytd() methods effectively do exactly the same task. We went in for this because we wanted to display how two identical threads, when assigned different priorities, work. With every step the value of ProgressBars are incremented by 20 till the value of ProgressBars reach 300 and then the thread aborts.

//place( ) Method 
 
public void place(ref Thread p, int x)
{
    switch(x)
    {
        case 0: 
            p.Priority = ThreadPriority.Lowest;
            break;
            
        case 1: 
            p.Priority = ThreadPriority.BelowNormal;
            break;
 
        case 2: 
            p.Priority = ThreadPriority.Normal;
            break;
 
        case 3: 
            p.Priority = ThreadPriority.AboveNormal;
            break;
 
        case 4: 
            p.Priority = ThreadPriority.Highest;
            break;
    }
}

place() method takes in a reference to a thread and the (int) index value captured through the ComboBoxs as its arguments. Then we assign prioities to the threads according to the value selected in the ComboBox.

Notes:

Unlike in Java where you can have priorities from 1 to 10 corresponding to MIN_PRIORITY to MAX_PRIOITY. You can assign any priority within this range i.e., 1 to 10. Whereas in C# you have only five of them. Lowest (0), BelowNormal (1), Normal (2), AboveNormal (3) and Highest (4).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Authors

Anshuman Dimri

United States United States
I am an Under Graduate (on the verge of completion of my Grads) from one of the most prestigious Universities in India - BITS, Pilani.

narendar

United States United States
dha dnbdk asnjdbnas mdb
djh dkas
d lndl sakd

Comments and Discussions

 
Questionworking code for vs 2010 Pinmemberjacob waswa5-Nov-12 0:53 
Questionwindows form or console appplication PinmemberEstherIfioky1-Oct-12 8:56 
AnswerRe: windows form or console appplication Pinmemberjacob waswa5-Nov-12 0:31 
GeneralRe: Threading in C# PingroupAnkitaaguggi9-Sep-11 23:31 
QuestionThreading in C# Pinmemberawadhendra tiwari30-Aug-11 1:52 
GeneralCross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on. PinmemberVidhuKumar12-May-11 21:05 
GeneralRe: Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on. Pinmembergihankoli24-Nov-11 7:18 
QuestionCross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on. PinmemberVidhuKumar12-May-11 21:02 
GeneralNot much helpfull PinmemberNavin C. Pandit14-Sep-09 1:57 
GeneralWorking code for Visual Studio 2003 Pinmemberlaurentma9214-Sep-07 0:37 
GeneralThis programe can not work in .net2005 Pinmembersun_jeri@163.com17-Aug-06 20:52 
GeneralRe: solution for you is... Pinmemberaristo/samar14-Oct-06 14:56 
GeneralNo working PinmemberXHungChung23-Jul-06 16:56 
GeneralProvide a link to download the source code! PinsussAnonymous21-Jun-05 9:24 
GeneralRe: Provide a link to download the source code! PinsussAnonymous21-Jun-05 9:25 
GeneralIt doesn't work Pinmemberjanigorse17-Jul-04 1:46 
GeneralRe: It doesn't work PinmemberRobgeez5-Aug-04 23:45 
GeneralRe: It doesn't work Pinmembersk8rboy2-Nov-04 9:08 
GeneralWhy pass Thread as Ref PinmemberSatch12-Nov-02 20:58 
GeneralRe: Why pass Thread as Ref Pinmemberjeffshantz22-Nov-04 23:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140709.1 | Last Updated 22 May 2001
Article Copyright 2001 by Anshuman Dimri, narendar
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid