Skip to main content

Notes on Multi-Threading

1. System.Threading namespace provides classes and interfaces that enable multithreaded programming.

2. How to initiate new Thread?

    a. Create an object of a Thread class
       i. Argument should not be null
       ii. Should have permission to create thread.
       b. Its constructor takes an instance of a ThreadStart Class
    c. ThreadStart Class requires the method that needs to be run on new thread.
    d. Call the Start method of the thread class to initiate execution on this new thread.

3. Important points on Threading –

    a. Thread function can be static or non-static
    b. You can have multiple threads with same thread function.
    c. You should always assign a name to the thread using its Name property. (This was pointed out to me by Kalyan Krishna. He said it invaluable when it comes to debugging multi-threaded apps and I agree).

4. Sleep method –

    a. Sleep is a static method and can be called directly on the Thread class
    b. It suspends execution of the thread for specified duration.
    c. Accepts duration in millisecond as its argument.

5. Thread.Stop should not be used instead Thread.Abort should be used.

6. Thread.Abort will throw ThreadAbortedException.

7. Thread.Join can be used to wait for the thread to complete.

8. Overload of Thread.Join allows you to wait for the thread completion for specific duration.

9. IsBackground property can be set to mark the thread as background thread and it will terminate as the main thread / application terminates.

10. You can set the priority of the thread using its Priority property.

11. Thread Priority can be set to –

    a. ThreadPriority.Highest
    b. ThreadPriority.AboveNormal
    c. ThreadPriority.Normal
    d. ThreadPriority.BelowNormal
    e. ThreadPriority.Lowest

12. Thread.GetDomain() method can be used to get the name of the executable file in which the thread is executing.

13. ThreadPool – is a collection of threads that can be used to perform several tasks in the background.

14. ThreadPool.QueueUserWorkItem is used with a delegate for the procedure you want to run.

    a. Eg – ThreadPool.QueueUserWorkItem(new Threading.WaitCallback(YourMethodtoRun));

15. ThreadPool should not be used for picking up threads when working in the web applications.

16. CLR’s ThreadPool is a kind of Producer / consumer queue.

17. How to implement Begin/End or IAsyncResult Pattern for asynchronous programming?

    a. Create a class say AsyncResult that implements IAsyncResult interface
    b. This class should manage – an AsyncCallback, a ManualResetEvent, an object for sharing state information with parent thread and an Exception objects
    c. Handle – isCompleted, CompletedAsynchronously, AsyncWaitHandle, Complete, Validate properties and methods.
    d. Create another class say AsyncResultExtended that inherits AsyncResult class created above
    e. Use this to encapsulate the custom arguments for the Beginxxxxx method.
    f. Create your specific class that handles synchronous long running method say LongCall.
    g. Create your async method say BeginLongCall. This method should call on ThreadPool.QueueUserWorkItem with Run method and an object of the AsyncResultExtended class.
    h. In the Run method simply extract properties from the object of AsyncResultExtended class and call the synchronous method LongCall with correct arguments.
    i. Create your async method EndLongCall. This method should do the following –
        i. Accept an argument of type IAsyncResult type
        ii. Check if null then throw error
        iii. Call validate
        iv. Call WaitOne on the AsyncWaitHandle
        v. Extract return value
        vi. In the finally block call the Dispose method.

18. AsyncWaitHandle – is used to wait for the asynchronous operation to complete.

19. You can use WaitOne, WaitAny or WaitAll on AsyncWaitHandle

20. How to call a method asynchronously?

    a. Define a delegate with the same signature as that of the method you wish to call asynchronously.
    b. Call BeginInvoke which will initiate the asynchronous call.
    c. It will have same parameters as the original method plus two additional optional arguments.
        i. AsyncCallback that takes the reference to the method that needs to be invoked when asynchronous processing is complete
        ii. User defined object that passes information into the callback method.
    d. It will return an object of type IAsyncResult which can be used to monitor the progress of the asynchronous call.
    e. Call EndInvoke method which can be called anytime after BeginInvoke but will block further execution till asynchronous call completes.
    f. It will have all the out and ref arguments from the BeginInvoke and finally the IAsyncResult type argument which was returned from the BeginInvoke call.
    g. Eg –
        i. Public class SlowProcessor { Public string LongRunningMethod(int iteration); }
        ii. Public delegate string LongMethodCaller(int iteration);
        iii. SlowProcessor proc = new SlowProcessor();
        iv. LongMethodCaller caller = new LongMethodCaller(proc.LongRunningMethod);
        v. IAsyncResult result = caller.BeginInvoke(10, null, null);
        vi. String str = caller.EndInvoke(result);

21. Lock keyword marks a statement block as a critical section by obtaining the mutual exclusion lock for a given object.

    a. It is faster and more convenient
    b. This is a syntactical shortcut for a call to methods Monitor.Enter() and Monitor.Exit() with a try / finally block.
    c. Eg –
        i. private object mylock = new object();
        ii. lock (mylock) { //do critical statements here }

22. Mutex is a synchronization primitive that can be used for interprocess synchronization.

    a. It grants exclusive access to the shared resource to only one thread.
    b. It can span application in different processes
    c. WaitHandle.WaitOne can be used to acquire ownership of a Mutex.
    d. Thread must call ReleaseMutex.
    e. It enforces thread identity, which is the mutex can be released only by the thread that acquired it.
    f. If a thread owning a mutex is terminated then the mutex is said to be abandoned and will throw AbandonedMutexException when next acquired by anyother thread.
    g. These are of two types – local mutex which are unnamed and named system mutex
    h. Eg –
        i. Private static Mutex mtx = new Mutex();
        ii. Private static void UseResource() {
        iii. mtx.WaitOne();
        iv. // do something here
        v. mtx.ReleaseMutex();}

23. Semaphore – Its like a bus with certain capacity, once full a queue builds up outside. Then with each thread exiting the bus another thread is allowed inside from the queue.

    a. This does not enforce thread identity and hence is thread-agnostic.
    b. Semaphore with a capacity of 1 is similar to Mutex or lock.
    c. Any thread can call Release on a Semaphore.
    d. SemaphoreSlim introduced in .net 4 is more optimized.
    e. Eg –
        i. static SemaphoreSlim ss = new SemaphoreSlim(3);
        ii. ss.Wait();
        iii. // do some code here
        iv. ss.Release();

24. Event Wait Handles are used for signaling.

25. Event Wait Handles are the simplest form of signaling constructs.

26. There are three types of Event Wait Handles –

    a. AutoResetEvent
    b. ManualResetEvent
    c. CountdownEvent

27. AutoResetEvent – is like a turnstile: inserting a ticket lets exactly one person through.

    a. A Thread waits by calling WaitOne
    b. Any unblocked thread with reference to AutoResetEvent can call Set on it to release one blocked thread.
    c. Reset on an AutoResetEvent will close the turnstile.

28. ManualResetEvent – is like an ordinary gate.

    a. Calling Set on this will open the gate.
    b. Now any number of threads that have called WaitOne will be let through.
    c. Calling Reset on this will close the gate.
    d. Now any number of threads that have called WaitOne will be blocked.

29. CountDownEvent – lets you wait on more than one thread by specifying the number in its constructor.

30. Synchronization Context – To implement auto locking declaratively.

    a. Derive your class from ContextBoundObject
    b. Assign attribute [Synchronization] to the class.
    c. This will instruct the CLR to apply locking automatically.

References -

http://www.albahari.com/threading/part2.aspx

Comments

Anonymous said…
nice article.

Please eaborate more on why ThreadPool shouldn't be used in web?

Also one addon. What if a method takes input as int x, int y instead of one object type like:
public static void xyz (int a, int b)

To start a thread on such method, the way is:
Thread T3 = new Thread(() => xyz(3, 4));
Abhy Nadar said…
@enabledeepak - Using BeginInvoke or ThreadPool.QueueUserWorkItem utilizes threads from the ThreadPool, whereas when you create a Thread using System.Threading.Thread you create a new non pooled thread. In cases of highly multi-threaded systems like ASP.Net application you might end up impacting the servicing threads.

To start thread with multiple arguments you can also create a delegate and use its BeginInvoke.

Popular posts from this blog

Notes on Castle MonoRail

  Sometime back I was doing a small POC on Castle MonoRail. So here are my quick notes on this. MonoRail is an MVC Framework from Castle inspired by ActionPack. MonoRail enforces separation of concerns with Controller handling application flow, models representing data and View taking care of the presentation logic. To work with MonoRail you need Castle Assemblies. It also utilizes nHibernate You can use Castle MonoRail Project Wizard or create the project manually. Project structure – Content Css Images Controllers HomeController.cs Models Views Home \ index.vm Layouts \ Default.vm ...

Workflow Foundation 4 - Part 3 - Data storage and management

This is my third post on WF4. First one was an introductory post on WF4 and in second one we focused on executing workflows. In the this post I am going to focus on the topic of data storage and management. Every business process or flow depends on data. When you think of data there are three elements to it as listed below - Variables - for storing data Arguments - for passing data Expressions - for manipulating data. Let us first look at the variables. Variables are storage locations for data. Variables are declared before using them just like in any other languages like C# or VB.Net. Variables are defined with a specific scope. When you create a variable in an activity the scope of the variable becomes that activity's scope. Variables can also have access modifiers like None, Mapped or ReadOnly. Let us look at an example where we will create two variables and assign a scope to them along with access modifiers. //Declare a sequence activitiy Sequence seqWf = new Sequence(); //de...

Introduction to Workflow Foundation 4 (WF4)

I finally decided to pick-up my blogging once more. Since I have been trying to learn Windows Workflow Foundation 4 (WF4) I thought I might as well start off with this topic. WF4 is a development framework that enables you to create a workflow and embed it in a .Net application. It is neither an executable application nor a language. It provides a set of tools for declaring a workflow, activities to create your logic and to define control flow and a runtime for executing the resulting application definition. It also provides services for persistence of state, tracking and bookmarking. You can create your workflow directly in code, in mark-up or in a combination of both. Workflow provide us with two major advantages - Creating unified application logic. Making application logic scalable. Workflow Authoring styles - Sequential Workflow executes a set of contained activities in a sequential manner. Workflow Foundation was introduced in the .Net 3.0 and updated in 3.5. In .net 4 it has bee...