Click here to Skip to main content
Click here to Skip to main content
Go to top

Converting single threaded C# class to multithreaded one

, 24 Oct 2003
Rate this:
Please Sign up or sign in to vote.
The article desribribes the technique and the software tool for conversion of single threaded classes to multithreaded.

Sample Image - AmThreader.png

Terms definition

Straight after the publishing of this article, I received criticism from number of readers including the reader dog_spawn: "How can you ever call a class 'single threaded' or 'multithreaded'? I have programmed using threads for years (C++, Java and recently C#) but your article makes absolutely no sense to me". In fact, he is right - there is no such a thing as single threaded or multithreaded class, on the other hand, I do not have better name for the construction I have created. Perhaps, I can name it a Thread Isolator. To avoid further misunderstanding, I would like to make clear that AmThreader is a code generator that creates a class wrapper for any .NET class (not necessarily C#), and any call of wrapper class method will be translated to original class call but in a separate thread.

Introduction

All of us use computers today. You start an application, click controls, and at some moment it stops to respond. Well, the most probable cause of it is that the main thread is unable to exit (or continue) for some reason. What reason? The reason in fact, can be any: Input-Output cannot complete, some network problems, internal application error, and the thread went into endless loop etc. Very annoying situation, indeed. How can this problem be resolved? The only way to create a responsive, and in a certain sense, robust application is to use multithreading. However, everything is at cost because the development of multithreaded applications is more complicated. It involves threads synchronization, considerably more complicated debugging, and so on. That is why even reputable companies still use single threading. So, how to simplify the development of multithreaded software?

Code Generator

The answer is AmThreader - the code generator. It converts any single threaded .NET class to multithreaded one. How it works?

Let's look first into the stages of the development of simple multithreaded applications. What are the components of multithreading? Nothing in fact is really special:

  1. Temporary variables for holding and passing the parameters from one thread to another.
  2. A new thread (worker thread).
  3. Methods to invoke certain methods in the worker thread.
  4. A loop that runs in the worker thread.
  5. A bunch of enums, switches and cases that control the work flow in the worker thread.
  6. Wait procedure (or extra thread).
  7. Threads synchronization components (depend on OS and used language).
  8. Exception handling.

For instance, we have a class ClassA that has the method DoSomething() which may not return.

using System;

namespace SomeNameSpace 
{ 
public class ClassA 
    { 
        public ClassA() 
        { 
        }
        public void DoSomething(int b) 
        {
            // do something 
        } 
    } 
}

Let's convert it to a multithreaded one in order to make the application safe and friendly. Speaking in C# terms, this new class can be represented with a snippet below:

namespace SomeNameSpace 
{ 
    public class __ClassA : IDisposable
    { 
        private enum Commands_enums 
        { 
            ClassA__enum_0, 
            DoSomething__enum_1
        } 
        private Commands_enums CurrCommand; 
        private bool bError; 
        private bool ThreadStop; 
        private ManualResetEvent EventStart = new ManualResetEvent(false); 
        private object[] inParams = new object[100]; 
        private object ValueParam; 
        private Thread fThread; 
        private int nTimeOut = 10000; 
        private int CycleTime = 15; 
        private ClassA ThreadObjectInstance; 

        public __ClassA() 
        { 
            StartThread(); 
            CurrCommand = Commands_enums.ClassA__enum_0; 
            WaitForComplete(); 
        } 

        public void DoSomething(int b) 
        { 
            inParams[0] = b; 
            CurrCommand = Commands_enums.doSomething__enum_1; 
            WaitForComplete(); 
        } 

        private void Worker_Thread_01() 
        { 
            while(!ThreadStop) 
            { 
                EventStart.WaitOne(); 
                switch(CurrCommand) 
                { 
                    case Commands_enums.ClassA__enum_0: 
                      ThreadObjectInstance = new ClassA(); 
                      break; 

                    case Commands_enums.DoSomething__enum_1: 
                      ThreadObjectInstance.DoSomething((int)inParams[0]); 
                      break; 
                    default: 
                      break; 
            } 

        bStopWaiting = true; 
        CurrCommand = Commands_enums.wait_command__enum_; 

        EventStart.Reset(); 

        } 
    } 

    private void StartThread() 
    { 
        ThreadStart thr_start_func = new ThreadStart (Worker_Thread_01); 
        fThread = new Thread (thr_start_func); 
        fThread.Name = "Worker_Thread_01"; 
        fThread.Start (); //starting the thread 
    } 

    private void WaitForComplete() 
    { 
        int ElapsedTime = 0; 
        EventStart.Set(); 
        while(!bStopWaiting) 
        { 
            //** Place for event processing 
            ElapsedTime += CycleTime;
            if (ElapsedTime > nTimeOut) 
            { 
                    bStopWaiting = true; 
                    throw new Exception("Wait TimeOut"); 
            } 
            Thread.Sleep(CycleTime); 
        } 
    } 

    public void Dispose()
    {
        bStopWaiting = true;
        ThreadStop = true;
        EventStart.Set();
    }

}

The snippet above is the simplest ,though complete multithreaded class. Yes, it is simple, but what can it do? Not much, the only thing it can do well is wait for the completion of the DoSomething() method and announce its failure if the worker thread sticks in it. Even with this limited functionality, it is useful. The application can always be terminated gracefully, although the main thread is still frozen during the execution of DoSomething(). However, for event driven applications (all GUI or WinForms), there is a trick to overcome that unpleasant effect. We only need to place Application.DoEvents() inside Wait loop. The interface will still be responding during DoSomething(). The code line Thread.Sleep(CycleTime) controls the responsiveness of the interface. The smaller CycleTime, the more responsive the interface is, on the other hand, it uses more CPU resources.

How can the new class __ClassA be used? The same way the original class is.

For example: the original class ClassA can be used in the way something like this:

try 
{
    ClassA MyClassA = new ClassA();
    MyClassA.DoSomething(5); 
} 
catch(Exception ex) 
{ 
    MessageBox.Show(ex.Message); 
}

How to use the new class? Well, almost the same. The only difference is that the class must be destroyed explicitly calling Dispose(), otherwise the application will never end with worker thread running.

try
{ 
    __ClassA MyClassA = new __ClassA();
    MyClassA.DoSomething(5); 
    MyClassA.Dispose();
}
catch(Exception ex)
{
    MessageBox.Show(ex.Message);
}

So, what is so special in __ClassA and how can it be derived (not in the sense of inheritance) from ClassA? Absolutely nothing and this operation can be automated completely.

Using Reflection, AmThreder generates a new class from the Assembly with the same method names, indexers, and properties as the original class has. Only public methods are processed, even the source code of the original class is no longer needed.

Where to download

To download fresh version of AmThreader, visit http://www.amplefile.com/, "downloads" page. AmThreader constantly monitors if fresh version is available and will notify you.

History

  • Initial version - 1.0.2.0
  • Current version - 1.0.4.0

License

For independent developers, AmThreader is free. However it has to be registered.

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

Share

About the Author

Alex_1
Web Developer
Australia Australia
No Biography provided

Comments and Discussions

 
GeneralNice... Pinmemberro_angel_bv15-Apr-04 5:55 
GeneralStarting a new thread in context of constructor PinmemberENewton1-Dec-03 11:02 
Probably not a very scalable idea... instead the "do work" thread should be lazily created during the call to DoSomething()
 
Note also that OS Threads are costly to create and costly to run, so if you have 100 or even 1000 of these "thread wrapped" classes operating, you're gonna get major thrashing.
 
An improvement on the idea would be to lazily acquire a thread from a thread pool (optionally configurable) in the DoSomething() method...
 
The scariest aspect of this is the potential for a mass number of threads in, for example, an asp.net application that utilizes the class...
GeneralDon't get it Pinmemberdog_spawn13-Oct-03 9:22 
GeneralRe: Don't get it Pinmemberdog_spawn13-Oct-03 14:22 
GeneralRe: Don't get it PinmemberNormski14-Oct-03 20:48 
GeneralRe: Don't get it PinsussAnonymous200515-Apr-04 6:23 
GeneralRe: Installation not working Pinmemberrstaylor16-Oct-03 5:13 
GeneralRe: Installation not working PinmemberAlex_116-Oct-03 11:38 

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.140916.1 | Last Updated 25 Oct 2003
Article Copyright 2003 by Alex_1
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid