Hii
I want to work with MultyThreading concept and I am using the following code.
But when i try to run the the MultiThreading (multiThreadedButton_Click()) its giving an error at
FillList() function.

The code is :

private void Delay(int v_MilliSeconds)
   {
      long startTime = Environment.TickCount;
      while( Environment.TickCount - startTime < v_MilliSeconds )
       {
       }
   }

    /*
        * Fill the listbox with hello world buttons.  Pause for a period
        * of time between each message.
    */

        private void FillList()
        {
            responseList.Items.Clear();
            responseCountLabel.Text = "0";
            ToggleButtons(false);
            for (int i = 0; i < 10; i++)
            {
                responseList.Items.Add("Thread #" + i);
                this.Delay(1000);
            }
            this.ToggleButtons(true);
        }

        /*
         * Toggle the form buttons on or off accordingly.
         */
        private void ToggleButtons(bool v_Toggle)
        {
            this.nonThreadedButton.Enabled = v_Toggle;
            this.multiThreadedButton.Enabled = v_Toggle;
        }

        private void testResponseButton_Click(object sender, EventArgs e)
        {
            this.responseCountLabel.Text =
            Convert.ToString(Convert.ToInt32(this.responseCountLabel.Text) + 1);

        }

        private void multiThreadedButton_Click(object sender, EventArgs e)
        {
             // Launch a thread to do the update
            System.Threading.Thread sampleThread =
            new System.Threading.Thread(
            new System.Threading.ThreadStart(this.FillList));
            sampleThread.Start();

        }

The error is :

Cross-thread operation not valid: Control 'responseCountLabel' accessed from a thread other than the thread it was created on.

Please help me..

Thanks in Advance.

This code will work(Sorry it is in Vb):

Public Class Form1
    Private responseList As New ArrayList()
    Private m_Toggle As Boolean
    Private Delegate Sub ThreadAccessControls()
    Private Sub AccessControls()
        If m_Toggle Then
            responseCountLabel.Text = "List contains " + responseList.Count.ToString + " elements"
            nonThreadedButton.Enabled = m_Toggle
            multiThreadedButton.Enabled = m_Toggle
        Else
            responseCountLabel.Text = "0"
            nonThreadedButton.Enabled = m_Toggle
            multiThreadedButton.Enabled = m_Toggle
        End If
    End Sub
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles nonThreadedButton.Click
    End Sub
    Private Sub multiThreadedButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles multiThreadedButton.Click
        ' Launch a thread to do the update
        Dim sampleThread As New System.Threading.Thread(New System.Threading.ThreadStart(AddressOf FillList))
        sampleThread.Start()
    End Sub
    Private Sub Delay(ByVal v_MilliSeconds As Integer)
        Dim startTime As Long = Environment.TickCount
        While (Environment.TickCount - startTime < v_MilliSeconds)
        End While
    End Sub
    Private Sub FillList()
        responseList.Clear()
        m_Toggle = False
        Dim access As New ThreadAccessControls(AddressOf AccessControls)
        Invoke(access, Nothing)
        'responseCountLabel.Text = "0"
        'ToggleButtons(False)
        For i As Integer = 0 To 10
            responseList.Add("Thread #" + i.ToString)
            Delay(1000)
        Next
        m_Toggle = True
        Invoke(access, Nothing)
        'ToggleButtons(True)
    End Sub
    'Private Sub ToggleButtons(ByVal v_Toggle As Boolean)
    '    nonThreadedButton.Enabled = v_Toggle
    '    multiThreadedButton.Enabled = v_Toggle
    'End Sub

End Class

Thanks for your suggetion :)
But again an error is coming (at the point u mentioned ) :sad:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace thrds
{
    public partial class Multithreaded : Form
    {
        public Multithreaded()
        {
            InitializeComponent();
        }
        private ArrayList responseList1 = new ArrayList();
        private bool m_Toggle;
        private delegate void ThreadAccessControls(); 

        private void AccessControls()
        {
            if (m_Toggle)
            {
                responseCountLabel.Text = "List contains " + responseList1.Count.ToString() + " elements";
                nonThreadedButton.Enabled = m_Toggle;
                multiThreadedButton.Enabled = m_Toggle;
            }
            else
            {
                responseCountLabel.Text = "0";
                nonThreadedButton.Enabled = m_Toggle;
                multiThreadedButton.Enabled = m_Toggle;
            }
        } 


        private void Multithreaded_Load(object sender, EventArgs e)
        {

        }

       
         /*
                * Deplay processing for the specificed number of milliseconds
         */
   private void Delay(int v_MilliSeconds)
   {
       long startTime = Environment.TickCount;
       while ((Environment.TickCount - startTime < v_MilliSeconds))
       {
       } 

   }

    /*
        * Fill the listbox with hello world buttons.  Pause for a period
        * of time between each message.
    */

        private void FillList()
        {
            responseList.Clear();
            m_Toggle = false;
            ThreadAccessControls access = new ThreadAccessControls(new EventHandler(AccessControls));
            Invoke(access, null);
            for (int i = 0; i <= 10; i++)
            {
                responseList1.Add("Thread #" + i.ToString());
                Delay(1000);
            }
            m_Toggle = true;
            Invoke(access, null); 

        }

        /*
         * Toggle the form buttons on or off accordingly.
         */
        private void ToggleButtons(bool v_Toggle)
        {
            this.nonThreadedButton.Enabled = v_Toggle;
            this.multiThreadedButton.Enabled = v_Toggle;
        }

        private void testResponseButton_Click(object sender, EventArgs e)
        {
            this.responseCountLabel.Text =
            Convert.ToString(Convert.ToInt32(this.responseCountLabel.Text) + 1);
        }

        private void multiThreadedButton_Click(object sender, EventArgs e)
        {
            System.Threading.Thread sampleThread = new System.Threading.Thread(new System.Threading.ThreadStart(new EventHandler(FillList)));
            sampleThread.Start(); 

        }

        private void nonThreadedButton_Click(object sender, EventArgs e)
        {
            this.FillList();
        }


    }
}

the errors are:
Error 10 No overload for 'AccessControls' matches delegate 'System.EventHandler' C:\Documents and Settings\SRAVAN\My Documents\Visual Studio 2005\Projects\thrds\thrds\Multithreaded.cs 66 68 thrds

Error 11 No overload for 'FillList' matches delegate 'System.EventHandler' C:\Documents and Settings\SRAVAN\My Documents\Visual Studio 2005\Projects\thrds\thrds\Multithreaded.cs 95 113 thrds


This code will work(Sorry it is in Vb):

Public Class Form1
    Private responseList As New ArrayList()
    Private m_Toggle As Boolean
    Private Delegate Sub ThreadAccessControls()
    Private Sub AccessControls()
        If m_Toggle Then
            responseCountLabel.Text = "List contains " + responseList.Count.ToString + " elements"
            nonThreadedButton.Enabled = m_Toggle
            multiThreadedButton.Enabled = m_Toggle
        Else
            responseCountLabel.Text = "0"
            nonThreadedButton.Enabled = m_Toggle
            multiThreadedButton.Enabled = m_Toggle
        End If
    End Sub
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles nonThreadedButton.Click
    End Sub
    Private Sub multiThreadedButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles multiThreadedButton.Click
        ' Launch a thread to do the update
        Dim sampleThread As New System.Threading.Thread(New System.Threading.ThreadStart(AddressOf FillList))
        sampleThread.Start()
    End Sub
    Private Sub Delay(ByVal v_MilliSeconds As Integer)
        Dim startTime As Long = Environment.TickCount
        While (Environment.TickCount - startTime < v_MilliSeconds)
        End While
    End Sub
    Private Sub FillList()
        responseList.Clear()
        m_Toggle = False
        Dim access As New ThreadAccessControls(AddressOf AccessControls)
        Invoke(access, Nothing)
        'responseCountLabel.Text = "0"
        'ToggleButtons(False)
        For i As Integer = 0 To 10
            responseList.Add("Thread #" + i.ToString)
            Delay(1000)
        Next
        m_Toggle = True
        Invoke(access, Nothing)
        'ToggleButtons(True)
    End Sub
    'Private Sub ToggleButtons(ByVal v_Toggle As Boolean)
    '    nonThreadedButton.Enabled = v_Toggle
    '    multiThreadedButton.Enabled = v_Toggle
    'End Sub

End Class

Thanks for your suggetion :)
But again an error is coming (at the point u mentioned ) :sad:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
 
namespace thrds
{
    public partial class Multithreaded : Form
    {
        public Multithreaded()
        {
            InitializeComponent();
        }
        private ArrayList responseList1 = new ArrayList();
        private bool m_Toggle;
        private delegate void ThreadAccessControls(); 
 
        private void AccessControls()
        {
            if (m_Toggle)
            {
                responseCountLabel.Text = "List contains " + responseList1.Count.ToString() + " elements";
                nonThreadedButton.Enabled = m_Toggle;
                multiThreadedButton.Enabled = m_Toggle;
            }
            else
            {
                responseCountLabel.Text = "0";
                nonThreadedButton.Enabled = m_Toggle;
                multiThreadedButton.Enabled = m_Toggle;
            }
        } 
 
 
        private void Multithreaded_Load(object sender, EventArgs e)
        {
 
        }
 
 
         /*
                * Deplay processing for the specificed number of milliseconds
         */
   private void Delay(int v_MilliSeconds)
   {
       long startTime = Environment.TickCount;
       while ((Environment.TickCount - startTime < v_MilliSeconds))
       {
       } 
 
   }
 
    /*
        * Fill the listbox with hello world buttons.  Pause for a period
        * of time between each message.
    */
 
        private void FillList()
        {
            responseList.Clear();
            m_Toggle = false;
            ThreadAccessControls access = new ThreadAccessControls(new EventHandler(AccessControls));
            Invoke(access, null);
            for (int i = 0; i <= 10; i++)
            {
                responseList1.Add("Thread #" + i.ToString());
                Delay(1000);
            }
            m_Toggle = true;
            Invoke(access, null); 
 
        }
 
        /*
         * Toggle the form buttons on or off accordingly.
         */
        private void ToggleButtons(bool v_Toggle)
        {
            this.nonThreadedButton.Enabled = v_Toggle;
            this.multiThreadedButton.Enabled = v_Toggle;
        }
 
        private void testResponseButton_Click(object sender, EventArgs e)
        {
            this.responseCountLabel.Text =
            Convert.ToString(Convert.ToInt32(this.responseCountLabel.Text) + 1);
        }
 
        private void multiThreadedButton_Click(object sender, EventArgs e)
        {
            System.Threading.Thread sampleThread = new System.Threading.Thread(new System.Threading.ThreadStart(new EventHandler(FillList)));
            sampleThread.Start(); 
 
        }
 
        private void nonThreadedButton_Click(object sender, EventArgs e)
        {
            this.FillList();
        }
 
 
    }
}

the errors are:
Error 10 No overload for 'AccessControls' matches delegate 'System.EventHandler' C:\Documents and Settings\SRAVAN\My Documents\Visual Studio 2005\Projects\thrds\thrds\Multithreaded.cs 66 68 thrds

Error 11 No overload for 'FillList' matches delegate 'System.EventHandler' C:\Documents and Settings\SRAVAN\My Documents\Visual Studio 2005\Projects\thrds\thrds\Multithreaded.cs 95 113 thrds

Error sare compilation errors
Methods AccessControls and FillList are not Event Handlers, there are simple Delegates. Here is working C# code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace ThreadingTestCS
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
       
        private ArrayList responseList = new ArrayList();
        private bool m_Toggle;
        private delegate void ThreadAccessControls(); 
        private void AccessControls()
        {
            if (m_Toggle)
            {
                responseCountLabel.Text = "List contains " + responseList.Count.ToString() + " elements";
                nonThreadedButton.Enabled = m_Toggle;
                multiThreadedButton.Enabled = m_Toggle;
            }
            else
            {
                responseCountLabel.Text = "0";
                nonThreadedButton.Enabled = m_Toggle;
                multiThreadedButton.Enabled = m_Toggle;
            }
        } 

        private void Multithreaded_Load(object sender, EventArgs e)
        {
        }
       
         /*
                * Deplay processing for the specificed number of milliseconds
         */
   private void Delay(int v_MilliSeconds)
   {
       long startTime = Environment.TickCount;
       while ((Environment.TickCount - startTime < v_MilliSeconds))
       {
       } 
   }
    /*
        * Fill the listbox with hello world buttons.  Pause for a period
        * of time between each message.
    */
        private void FillList()
        {
            responseList.Clear();
            m_Toggle = false;
            ThreadAccessControls access = new ThreadAccessControls(AccessControls);
            Invoke(access, null);
            for (int i = 0; i <= 10; i++)
            {
                responseList.Add("Thread #" + i.ToString());
                Delay(1000);
            }
            m_Toggle = true;
            Invoke(access, null); 
        }
        /*
         * Toggle the form buttons on or off accordingly.
         */
        private void ToggleButtons(bool v_Toggle)
        {
            this.nonThreadedButton.Enabled = v_Toggle;
            this.multiThreadedButton.Enabled = v_Toggle;
        }
        private void testResponseButton_Click(object sender, EventArgs e)
        {
            this.responseCountLabel.Text =
            Convert.ToString(Convert.ToInt32(this.responseCountLabel.Text) + 1);
        }
        private void multiThreadedButton_Click(object sender, EventArgs e)
        {
            System.Threading.Thread sampleThread = new System.Threading.Thread(new System.Threading.ThreadStart(FillList));
            sampleThread.Start(); 
        }
        
       

    }
}

Thanks for ur suggetion
But again the first error is comig :sad:
While clicking "nonThreadedButton" runtime error is coming at Fill list
The Error is
"Cross-thread operation not valid: Control 'responseList' accessed from a thread other than the thread it was created on."

AT

responseList.Items.Add("Thread #" + i.ToString());


Error sare compilation errors
Methods AccessControls and FillList are not Event Handlers, there are simple Delegates. Here is working C# code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace ThreadingTestCS
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
       
        private ArrayList responseList = new ArrayList();
        private bool m_Toggle;
        private delegate void ThreadAccessControls(); 
        private void AccessControls()
        {
            if (m_Toggle)
            {
                responseCountLabel.Text = "List contains " + responseList.Count.ToString() + " elements";
                nonThreadedButton.Enabled = m_Toggle;
                multiThreadedButton.Enabled = m_Toggle;
            }
            else
            {
                responseCountLabel.Text = "0";
                nonThreadedButton.Enabled = m_Toggle;
                multiThreadedButton.Enabled = m_Toggle;
            }
        } 

        private void Multithreaded_Load(object sender, EventArgs e)
        {
        }
       
         /*
                * Deplay processing for the specificed number of milliseconds
         */
   private void Delay(int v_MilliSeconds)
   {
       long startTime = Environment.TickCount;
       while ((Environment.TickCount - startTime < v_MilliSeconds))
       {
       } 
   }
    /*
        * Fill the listbox with hello world buttons.  Pause for a period
        * of time between each message.
    */
        private void FillList()
        {
            responseList.Clear();
            m_Toggle = false;
            ThreadAccessControls access = new ThreadAccessControls(AccessControls);
            Invoke(access, null);
            for (int i = 0; i <= 10; i++)
            {
                responseList.Add("Thread #" + i.ToString());
                Delay(1000);
            }
            m_Toggle = true;
            Invoke(access, null); 
        }
        /*
         * Toggle the form buttons on or off accordingly.
         */
        private void ToggleButtons(bool v_Toggle)
        {
            this.nonThreadedButton.Enabled = v_Toggle;
            this.multiThreadedButton.Enabled = v_Toggle;
        }
        private void testResponseButton_Click(object sender, EventArgs e)
        {
            this.responseCountLabel.Text =
            Convert.ToString(Convert.ToInt32(this.responseCountLabel.Text) + 1);
        }
        private void multiThreadedButton_Click(object sender, EventArgs e)
        {
            System.Threading.Thread sampleThread = new System.Threading.Thread(new System.Threading.ThreadStart(FillList));
            sampleThread.Start(); 
        }
        
       

    }
}

All controls on the form should be accessed from the delegate.
Code i send to jou works perfect on my machine.
Error you are receiving inicates that variable 'responseList' is Controll which is not case in my code , it is simly ArreyList instance declared as private memeber.
Here is my Form1.Designer.cs file

namespace ThreadingTestCS
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #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.components = new System.ComponentModel.Container();
            this.nonThreadedButton = new System.Windows.Forms.Button();
            this.multiThreadedButton = new System.Windows.Forms.Button();
            this.responseCountLabel = new System.Windows.Forms.Label();
            this.loadingPB = new System.Windows.Forms.ProgressBar();
            this.loadingTimer = new System.Windows.Forms.Timer(this.components);
            this.SuspendLayout();
            // 
            // nonThreadedButton
            // 
            this.nonThreadedButton.Location = new System.Drawing.Point(12, 201);
            this.nonThreadedButton.Name = "nonThreadedButton";
            this.nonThreadedButton.Size = new System.Drawing.Size(136, 23);
            this.nonThreadedButton.TabIndex = 0;
            this.nonThreadedButton.Text = "non Threaded Button";
            this.nonThreadedButton.UseVisualStyleBackColor = true;
            this.nonThreadedButton.Click += new System.EventHandler(this.nonThreadedButton_Click);
            // 
            // multiThreadedButton
            // 
            this.multiThreadedButton.Location = new System.Drawing.Point(154, 201);
            this.multiThreadedButton.Name = "multiThreadedButton";
            this.multiThreadedButton.Size = new System.Drawing.Size(126, 23);
            this.multiThreadedButton.TabIndex = 1;
            this.multiThreadedButton.Text = "multi Threaded Button";
            this.multiThreadedButton.UseVisualStyleBackColor = true;
            this.multiThreadedButton.Click += new System.EventHandler(this.multiThreadedButton_Click);
            // 
            // responseCountLabel
            // 
            this.responseCountLabel.AutoSize = true;
            this.responseCountLabel.Location = new System.Drawing.Point(52, 53);
            this.responseCountLabel.Name = "responseCountLabel";
            this.responseCountLabel.Size = new System.Drawing.Size(35, 13);
            this.responseCountLabel.TabIndex = 2;
            this.responseCountLabel.Text = "label1";
            // 
            // loadingPB
            // 
            this.loadingPB.Location = new System.Drawing.Point(12, 147);
            this.loadingPB.Name = "loadingPB";
            this.loadingPB.Size = new System.Drawing.Size(268, 23);
            this.loadingPB.TabIndex = 3;
            this.loadingPB.Visible = false;
            // 
            // loadingTimer
            // 
            this.loadingTimer.Tick += new System.EventHandler(this.loadingTimer_Tick);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(292, 266);
            this.Controls.Add(this.loadingPB);
            this.Controls.Add(this.responseCountLabel);
            this.Controls.Add(this.multiThreadedButton);
            this.Controls.Add(this.nonThreadedButton);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();
        }
        #endregion
        private System.Windows.Forms.Button nonThreadedButton;
        private System.Windows.Forms.Button multiThreadedButton;
        private System.Windows.Forms.Label responseCountLabel;
        private System.Windows.Forms.ProgressBar loadingPB;
        private System.Windows.Forms.Timer loadingTimer;
    }
    }
 //here is Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace ThreadingTestCS
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private ArrayList responseList = new ArrayList();
        private bool m_Toggle;
        private delegate void ThreadAccessControls(); 
        private void AccessControls()
        {
            if (m_Toggle)
            {
                responseCountLabel.Text = "List contains " + responseList.Count.ToString() + " elements";
                nonThreadedButton.Enabled = m_Toggle;
                multiThreadedButton.Enabled = m_Toggle;
                loadingTimer.Enabled = false;
                loadingPB.Visible = false;
            }
            else
            {
                responseCountLabel.Text = "Please wait loading List";
                loadingTimer.Interval = 10;
                loadingTimer.Enabled = true;
                loadingPB.Visible = true;
                nonThreadedButton.Enabled = m_Toggle;
                multiThreadedButton.Enabled = m_Toggle;
            }
        } 

        private void Multithreaded_Load(object sender, EventArgs e)
        {
        }

         /*
                * Deplay processing for the specificed number of milliseconds
         */
   private void Delay(int v_MilliSeconds)
   {
       long startTime = Environment.TickCount;
       while ((Environment.TickCount - startTime < v_MilliSeconds))
       {
       } 
   }
    /*
        * Fill the listbox with hello world buttons.  Pause for a period
        * of time between each message.
    */
        private void FillList()
        {
            responseList.Clear();
            m_Toggle = false;
            ThreadAccessControls access = new ThreadAccessControls(AccessControls);
            Invoke(access, null);
            for (int i = 0; i <= 10; i++)
            {
                responseList.Add("Thread #" + i.ToString());
                Delay(1000);
            }
            m_Toggle = true;
            Invoke(access, null); 
        }
        /*
         * Toggle the form buttons on or off accordingly.
         */
        private void ToggleButtons(bool v_Toggle)
        {
            this.nonThreadedButton.Enabled = v_Toggle;
            this.multiThreadedButton.Enabled = v_Toggle;
        }
        private void testResponseButton_Click(object sender, EventArgs e)
        {
            this.responseCountLabel.Text =
            Convert.ToString(Convert.ToInt32(this.responseCountLabel.Text) + 1);
        }
        private void multiThreadedButton_Click(object sender, EventArgs e)
        {
            System.Threading.Thread sampleThread = new System.Threading.Thread(new System.Threading.ThreadStart(FillList));
            sampleThread.Start(); 
        }
        private void loadingTimer_Tick(object sender, EventArgs e)
        {
            loadingPB.Value ++;
            if (loadingPB.Value == 100)
            {
                loadingPB.Value = 0;
            }
        }
        private void nonThreadedButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }



    }
}

// Here is Program.cs

using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace ThreadingTestCS
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

As you can see variable responseList is not added to the controls collection of the form.

Hi,

Im new to this community and when searching for threading concepts stumbled into this post. I would like to add something.

The basic reason for a cross thread error is the fact that all controls are handled using internal threads. To by pass the internal threads and use the controls we go for delegates. U may find the following links usefull.

http://www.codersource.net/published/view/320/chapter_multithreading_with_windows_forms.aspx

http://www.simple-talk.com/dotnet/windows-forms/asynchronous-processing-in-.net-part-1-fundamentals/