Click here to Skip to main content
15,885,278 members
Articles / Desktop Programming / Windows Forms
Article

C# Threadding, one on one - an easy way to do multi-threadding

Rate me:
Please Sign up or sign in to vote.
2.52/5 (12 votes)
8 Jun 2007CPOL4 min read 32.8K   656   26   5
how to do threadding in .net with C# and update the UI from worker threads

Screenshot - threadding_test_screen01.jpg

Screenshot - threadding_test_screen02.jpg

Introduction

as you see in that screenshot i had 3 background threads , each doing some lenthy operation, but all 3 threads need to show their progress, so simply i will explain how to do that.

Background

I've been reading articles in the code project for a while (3 years actually) but i was struggling to find a good article about a tough subject which is threadding, and because i used to be a win32 developer back in the good old days, i know how painfull it is to do multi-threadding, also as a .net developer i know that the framework did an elegant job in makinf threadding easy, but not for beginners though, so i decided to put this article as a starting point for beginners to learn about threadding in .net, and specially about updating the UI (user interface) from another thread because it is the toughest thing to do for beginners.

Using the code

I've decided to make this as simple as i can, so the project is only a windows forms project developed in visual studio 2005 and contains only one form that shows the progress.

first thing i did was to drop the progress bars and buttons and of course i named them to make my life easier.

next i had to define a delegate for the worker thread that does some processing in the background, and it looks like this:

C#
private delegate void DoOperationDelegate(int seconds, ProgressBar pBar, Button button);

the delegate takes 3 arguments:

  • int seconds: which is the number of milli seconds to delay the operation
  • ProgressBar pBar: the progress bar associated to show current operation's progress
  • Button button: the button to enable after the operation is finished

so we are cool now about the delegate, we needed the method that will do the actual work and looks like that delegate, and here it is:

C#
private void DoOperation(int seconds, ProgressBar pBar, Button button)
{
    for (int i = 0; i <= 100; i++)
    {
        System.Threading.Thread.Sleep(seconds / 100);
        UpdateUI(button, pBar, i);
    }
}

it is very self-explaining, but lets talk about it for a little bit. as we can see the method has a for-loop from 0 to 100 which are value limits for the progress bar by default, so i am doing a 100 step operation and in each step i actually do nothing by Thread.Sleep(some time) and that some time is the total milleseconds given for the operation devided by 100 steps, but you can do actual lengthy work here and dont make the thread sleep.

after that sleep operation i call a very important method, which is the UpdateUI method, that actually shows the progress, also passing the progress bar and the button and the actual progress values

now lets examin the other part of the code which is the UpdateUI delegate

private

C#
delegate void UpdateUIDelegate(Button button, ProgressBar pBar, int value);

that delegate does take three arguments:

  • Button button: the button to enable after the operation is finished
  • ProgressBar pBar: the progress bar associated to show current operation's progress
  • int value: the current value of operation progress (0 - 100)

and we implemented that delegate with the following code:

C#
private void UpdateUI(Button button, ProgressBar pBar, int value)
{
    if (this.InvokeRequired)
    {
        UpdateUIDelegate d = UpdateUI;
        this.Invoke(d, new object[] {button, pBar, value });
        return;
    }

    
    if (value >= 100)
    {
        button.Enabled = true;
        pBar.Value = 100;
    }
    else
    {
        pBar.Value = value;
    }
}

as you can see , here is the actual thread Synchronization work, so in the first block of code , we checked the form property "InvokeRequired" to see if the method have been called from another thread or not, if this returns true, then we are running from another thread, so we need to tell the UI thread to do the work, not our current thread, and this is established by calling "this.Invoke" because the form (this) will run the delegated method on its thread and we passed the same parameters for the delegate in the same order we received them.

so when this happens the form's thread will execute our method, and when we check InvokeRequired we will find it = false and we continue updating our UI safely.

so far we are missing only one thing, the code to start the processing from a new thread

C#
private void startButton1_Click(object sender, EventArgs e)
{
    startButton1.Enabled = false;
    DoOperationDelegate d = new DoOperationDelegate(DoOperation);
    d.BeginInvoke(1000, progressBar1, startButton1, null, null);
}

in that code you see the event handler for the button click for the first process, and actually the three event handler for the three buttons are all the same, except for the arguments that they pass to the delegate, and after creating a new instance from the delegate they call "BeginInvoke" which will start a new thread and executes the referenced method with the passed parameteres, but one thing for you fellas to know that there are two extra parameters for the BeginInvoke method, and i passed them as nulls because i didnt need them and they are out of our beginner scope actually.

Points of Interest

my interest with this article was to learn safe threadding with you, and i hope i did a good job, i will try to post other advanced examples, but i think this is enough so far, have fun guys and thanks for reading the article

History

June 09, 2007: First release.

License

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


Written By
Architect Dot Labs Pty Ltd
Australia Australia
A trusted technology adviser and a seasoned consultant with 15 years of experience in IT industry focused on helping organisations build modern IT solutions that drive innovation and increase efficiency and end-user value.

With a strong business acumen, an entrepreneur character, and vast experience in software engineering, I started my own consulting business (Dot Labs Pty Ltd) with a mission to drive adoption of modern solution architecture, public cloud infrastructure, and industry best practices.

During my career, I gained an extensive hands-on experience of software engineering through architecture standards, patterns, and best practice through my work with various enterprise organisations and startups, while keeping track of emerging technology and industry trends.

Comments and Discussions

 
GeneralThanks for the article Pin
Member 28073901-Nov-10 21:02
Member 28073901-Nov-10 21:02 
GeneralMy vote of 1 Pin
albert_cook11-Aug-09 21:56
albert_cook11-Aug-09 21:56 
NewsRead this before you score this article Pin
Bishoy Demian9-Jun-07 20:57
Bishoy Demian9-Jun-07 20:57 
GeneralBackgroundWorker Pin
Glen Harvy9-Jun-07 5:23
Glen Harvy9-Jun-07 5:23 
GeneralRe: BackgroundWorker Pin
Bishoy Demian9-Jun-07 20:53
Bishoy Demian9-Jun-07 20:53 

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

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