Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Threads with Windows Forms Controls in Managed C++

0.00/5 (No votes)
17 Jan 2006 1  
This article explains Managed Threads with Windows Forms Controls

Introduction

The threads class is used to create and manipulate managed threads. In the .NET environment, it is the same class used for all .NET enabled languages. The .NET threads catch all the threads executed in the managed threads. We can't access the unmanaged threads from the managed threads. Thread.GetHashCode is used to find the managed threads. Managed threads are executed in the .NET Common Language Runtime environment. Microsoft doesn't recommend mixing managed and unmanaged threads.

Managed Threads

Managed threads start when the System.Threading.Thread.Start method is called. This method is used to start the managed threads. When a user creates the threads, we can use ThreadStart delegate or a ParameterizedThreadStart delegate for creating the threads. The ThreadStart delegate is used to start the thread without any parameters. We can pass the argument using the Start method.

The ParameterizedThreadStart delegate is used to create a thread to pass an Object as an argument. If we call the Start method more than once, it throws a ThreadStateException exception. The following example shows how to create the managed threads:

ref class ThreadClass
{
public:
   static void ThraedClassMethod()
   {
      /// Do work 
   }
};

ThreadClass ^ objclass = gcnew ThreadClass; 
ThreadStart^ mThread = gcnew   ThreadStart(objclass,&objclass::ThreadClasMethod);
Thread^ newThread = gcnew Thread(mThread);
newThread->Start();

The ThreadState and IsAlive properties are used to get a thread state. But Microsoft doesn't recommend using those methods as thread synchronization. The System.Threading.Thread.Sleep method is used to sleep the thread for current execution. We can't sleep another thread from thread function. The System.Threading.Timeout.Infinite waits for an infinite level or when calls to other threads are returned. If System.Threading.Thread.Abort is called, it will terminate.

In Managed threads, we will set thread priorities much like unmanaged threads. CLR assigned ThreadPriority.Normal for default level. We can get or set the priority of any thread with the Thread.Priority property. The Abort method is used to destroy the managed threads permanently. When the Abort method is called from the main method, a ThreadAbortException is thrown.

Windows Forms with Controls

Microsoft introduced a new set of libraries in the .NET Framework with object oriented technology for creating the smart client applications in Windows. Windows Forms doesn't relate to existing technology for creating Windows like MFC, ATL or WTL. Windows Forms support the entire .NET Framework, and several languages share the same set of class libraries with .NET features. For example, MFC developers can get the features for .NET. Microsoft allows developers to mix both MFC and Windows forms into a single project. New MFC classes are used to access the .NET Windows Forms controls.

In our example, Windows Forms access between the multiple threads. The progress bar shows progress with different threads. Each progress bar has a separate button called a Thread. If we click the individual buttons, the thread starts and runs separately. The Thread starts in click event.

Thread^ newThread = gcnew Thread(gcnew ParameterizedThreadStart(&ThreadProc3 ));
newThread->Start(this);

The parameteterizedThreadStart is used to pass the Windows Forms object to the thread function. The static method calls the safe thread function. If developers want to change the status for Windows Forms control taken by a thread, we should declare a delegate.

delegate void ProgressBarCallback(System::Object ^obj);

This delegate passes a Windows Forms object. We change the status for each progressbar. If you want to invoke methods synchronously, you can call the following code:

static void SafeThread4(System::Object ^obj)
{
     Form1 ^ob = (Form1^) obj;
    if(ob->progressBar4->InvokeRequired)
    {
        ProgressBarCallback ^d = gcnew ProgressBarCallback(SafeThread4);
        ob->Invoke(d,gcnew array<System::Object^>{ob});                
    }
    else
    {
        for ( int i = 1; i <= 10; i++ )
        {
            ob->progressBar4->PerformStep();
            Thread::Sleep( 80 );
        }
    }
}

Managed Threads and Exceptions

In .NET Framework 2.0, CLR handles unhandled exceptions in managed application.

Managed threads throws exception for the following situations:

  • ThreadAbortException throws when user calls Abort method.
  • AppDomainUnloadedException throws application domain in which the thread is executing is being unloaded.
  • CLR throws when the host processes terminate the thread by throwing internal exception.

When I created the sample application, I tried to access the control class from thread function. But, I got the following exception:

static void ThreadProc1(System::Object ^obj)
     {

        Form1 ^ob = (Form1^) obj;
        for ( int i = 0; i < 10; i++ )
         {
              ob->progressBar1->PerformStep();
            Thread::Sleep( 0 );
          }
      }

When I execute the above code, I get the following exception:

System.InvalidOperationException was unhandled
  Message="Cross-thread operation not valid: 
	Control 'progressBar1' accessed from a thread other than 
	the thread it was created on."
  Source="System.Windows.Forms"

It gives the stack trace too.

Conclusion

Each application domain starts with at least a single thread. The System.Threading.Thread class is used to create one or more number of threads in a managed environment. For a multithreaded application, the CPU switches between threads in a single process. If system uses multiple threads in multiprocessor environment, the thread switch changes between the multiple processors. Microsoft doesn't recommend mixing both managed and unmanaged threads. Managed threads are garbage collected. So, a developer doesn't care about cleaning up resources. So, we don't face the memory leak problem in managed threads. For creating the managed threads using best practices, read this.

History

  • 17th January, 2006: Initial post

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