5,427,303 members and growing! (19,218 online)
Email Password   helpLost your password?
General Programming » Threads, Processes & IPC » Threading     Intermediate

A C# class to invoke almost any method from a worker thread

By Xiangyang Liu 刘向阳

C# code that makes multithreading easier
C#Windows, .NET, .NET 1.0, .NET 1.1, Win2K, WinXP, Win2003VS.NET2002, Visual Studio, Dev

Posted: 2 Nov 2003
Updated: 2 Nov 2003
Views: 41,349
Bookmarked: 23 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
16 votes for this Article.
Popularity: 4.99 Rating: 4.14 out of 5
4 votes, 25.0%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
2 votes, 12.5%
4
10 votes, 62.5%
5

Introduction

To readers: This article was posted last week under a different title. I deleted it later because the code does not really make multithreading easier, it requires you to derive a class from my base class and then override a virtual method. The current version is much simpler. I hope you find it useful, too.

When programming with C/C++, you can create a new thread using the Win32 API CreateThread. This API allows you to pass the address of a function and a pointer as its parameter. The function will be executed in a new thread. But you cannot use just any function as the thread function and you have to cast the input pointer to a structure or a class to access various values you need in the thread function. Or you can access global variables within the thread function to get input values.

With .NET, threading is supposed to be easier. However, the thread function you use in .NET cannot take any input parameter directly. You need to do some work to pass parameters to your worker thread, you can find out how to do it from MSDN.

In this article, I will introduce a C# class, ThreadHelper, that allows you to call almost any method that takes any number of parameters from a new worker thread. For example, you can use it to call a method in a .NET framework class or a third-party DLL from a new thread. The helper class also provides a way for you to get the output value of your function from the new thread.

The ThreadHelper class

The purpose of this class is to hide some boring details of using the .NET thread classes and make it easier for you to create a new worker thread in your application. If you are the kind of developer who always wants to know everything in your application, then this class is probably of little interest to you.

Here are the public methods of the ThreadHelper class.

// the constructor

public ThreadHelper();
// set a parameter value for the method you want to invoke

public void SetParameter(Object oValue);
// set the delegate (pointer) of the method you want to invoke

publicvoid SetMethod(Delegate pMethod);
// start a new thread and execute the method you specified

public bool StartThread();
// wait for the worker thread to finish

// warning: this method will block until the new thread is terminated

public void WaitForThread();
// get the error string

public String GetErrorMessage();
// get the output value

public Object GetOutput();
// reset all data so that the object can be reused

public void Reset();

Suppose you have a class MyDataClass as follows. The static member function GetData connects to a specified database and executes a query to retrieve data into a DataSet object.

class MyDataClass
{
    public static DataSet GetData(String sConnection, String sSQL)
    {
        // the implementation

    };
};

You may want to call this static member function to get data from several different databases simultaneously. Using the ThreadHelper class, here is what you need to do:

  1. Define a delegate for the GetData method.
  2. Create ThreadHelper objects.
  3. Call methods SetParameter, SetMethod, and StartThread.
  4. To wait for the thread to finish and check error messages or output values, call methods WaitForThread, GetErrorMessage and GetOutput.

Here is the code for the above example:

// define a delegate (pointer) for your method

public delegate String myDelegate(String sConnection, String sSQL);
...
// create three helper objects

ThreadHelper objHelper1 = new ThreadHelper();
ThreadHelper objHelper2 = new ThreadHelper();
ThreadHelper objHelper2 = new ThreadHelper();
// set the delegate (pointer) of your method

objHelper1.SetMethod(new myDelegate(MyDataClass.GetData));
objHelper2.SetMethod(new myDelegate(MyDataClass.GetData));
objHelper3.SetMethod(new myDelegate(MyDataClass.GetData));
// set the connection string parameter

objHelper1.SetParameter(sConnection1);
objHelper2.SetParameter(sConnection2);
objHelper3.SetParameter(sConnection3);
// set the sql statement parameter

objHelper1.SetParameter(sStatement1);
objHelper2.SetParameter(sStatement2);
objHelper3.SetParameter(sStatement3);
// start the worker thread

objHelper1.StartThread();
objHelper2.StartThread();
objHelper3.StartThread();
// wait for the worker thread to finish

objHelper1.WaitForThread();
objHelper2.WaitForThread();
objHelper3.WaitForThread();
// process the output of the method called in the new thread

Object oOutput = ObjHelper1.GetOutput();
...

As you can see, it is easy to call a method from a new worker thread with the help of ThreadHelper and you don't have to know anything about the thread classes in .NET.

Note: If your method has multiple parameters, you need to call SetParameter multiple times and the calls have to be in the same order as the parameters appear in the method signature. The same ThreadHelper object cannot be used simultaneously in different threads. You need to use a separate helper object for each concurrently running thread. If you call the Reset method after the worker thread finishes, then the helper object can be reused to start another thread.

A test application

I have included a C# console application ThreadHelperTest.exe with this article. The application uses ThreadHelper to start two worker threads, each calls the non-static Test method of class MyTest. Here is the corresponding code:

...
public delegate bool TestCall(String sName, int nTest);
...
MyTest objTest = new MyTest();
ThreadHelper objHelper1 = new ThreadHelper();
ThreadHelper objHelper2 = new ThreadHelper();
objHelper1.SetMethod(new TestCall(objTest.Test));
objHelper2.SetMethod(new TestCall(objTest.Test));
objHelper1.SetParameter("Bill");
objHelper2.SetParameter("George");
objHelper1.SetParameter(1);
objHelper2.SetParameter(2);
objHelper1.StartThread();
objHelper2.StartThread();
objHelper1.WaitForThread();
objHelper2.WaitForThread();
String sError1 = objHelper1.GetErrorMessage();
String sError2 = objHelper2.GetErrorMessage();
if(sError1=="")
{
    System.Console.WriteLine("Output of test 1: " + 
                    objHelper1.GetOutput().ToString());
}
else System.Console.WriteLine("Error in test 1: " + sError1);
if(sError2=="")
{
    System.Console.WriteLine("Output of test 2: " + 
                  objHelper2.GetOutput().ToString());
}
else System.Console.WriteLine("Error in test 2: " + sError2);

The following is the console output from this test application:

Hello, Bill
This is test 1
The thread id is 2
Hello, George
This is test 2
The thread id is 3
Hello, Bill
This is test 1
The thread id is 2
Hello, George
This is test 2
The thread id is 3
Hello, Bill
This is test 1
The thread id is 2
Hello, George
This is test 2
The thread id is 3
Output of test 1: True
Output of test 2: True

Note: The ThreadHelper class is supposed to make your multithreading code easier. It uses DynamicInvoke internally, which may be a little slower than the standard way (late binding vs. early binding). Also, you need to make sure that the method you want to execute in a new thread is thread-safe if it will be used concurrently in multiple threads.

Thank you for reading my articles.

Recent updates

  • 11/04/2003
    • Changed title and text.
    • Simplified code a little bit.

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 Author

Xiangyang Liu 刘向阳



Location: United States United States

Other popular Threads, Processes & IPC articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 7 of 7 (Total in Forum: 7) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralNice helper classmemberRobert Rohde22:22 21 Feb '04  
GeneralRe: Nice helper classmemberXiangyang Liu3:25 22 Feb '04  
GeneralRe: Nice helper classmembereyoung7014:14 19 Jul '04  
GeneralHow is this any easier or better than ThreadPool?memberfuzzylintman5:41 11 Nov '03  
GeneralRe: How is this any easier or better than ThreadPool?memberXiangyang Liu8:43 11 Nov '03  
GeneralRe: How is this any easier or better than ThreadPool?memberfuzzylintman9:18 11 Nov '03  
GeneralRe: How is this any easier or better than ThreadPool?memberXiangyang Liu9:59 11 Nov '03  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 2 Nov 2003
Editor: Smitha Vijayan
Copyright 2003 by Xiangyang Liu 刘向阳
Everything else Copyright © CodeProject, 1999-2008
Web15 | Advertise on the Code Project