Threading and Asynchronous Pattern-C#读书笔记

1.      Create a thread

When a managed thread is created, the method that executes on the thread is represented by a ThreadStart delegate or a ParameterizedThreadStart delegate that is passed to the Thread constructor. The thread does not begin executing until the System.Threading.Thread.Start method is called. Execution begins at the first line of the method represented by the ThreadStart or ParameterizedThreadStart delegate.

1.1 Without parameters

void testMethod()

{ //do something here

}

If the method has no parameter, we should use ThreadStart delegate which shows the definiation in MSDN:

[ComVisibleAttribute(true)]

public delegate void ThreadStart ()

 

Example:

ThreadStart start = new ThreadStart(testMethod);

Thread t = new Thread(start);

t.Start();

1.2 With parameters

void testMethodWithP(obj str)

{ //do something here

}

If the method has the parameters, we should use ParameterizedThreadStart to replace ThreadStart delegate, here is the delegate ParameterizedThreadStart illustrated in MSDN

[ComVisibleAttribute(false)]

public delegate void ParameterizedThreadStart (

        Object obj

)

Parameters

obj

An object that contains data for the thread procedure. It’s the parameter that the method needed

 

Example:

Thread newThread = new Thread(

            new ParameterizedThreadStart(testMethodWithP));

newThread.Start(“Hello”);

2.      Thread control

·         Abort() – cause a special ThreadAbortException

·         Suspend() – Thread only pause and does not experience a exception

·         Interrupt() – suspend a thread, but only if the delegate routine calls the Monitor.Wait, Thread.Sleep, or Thread.Join method during porcessing

·         Resume() – resume to continue run the thread

·         Join() – if the word thread use mythread.Join() method, the main thread will be blocked until the work thread finished

3.      ThreadPool

The threads in the managed thread pool are background threads. That is, their IsBackground properties are true. This means that a ThreadPool thread will not keep an application running after all foreground threads have exited.

We use ThreadPool.QueueUserWorkItem method to create thread in threadpool, it has two types overload method:

ThreadPool.QueueUserWorkItem (WaitCallback)

Queues a method for execution. The method executes when a thread pool thread becomes available.

ThreadPool.QueueUserWorkItem (WaitCallback, Object)

Queues a method for execution, and specifies an object containing data to be used by the method

Here is an example which shows how to use ThreadPool:

ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc);

If the ThreadProc has a parameter, we can call the following method

ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc),objpar);

Note: 

[ComVisibleAttribute(true)]

public delegate void WaitCallback (

        Object state

)

 WaitCallback: Represents a callback method to be executed by a thread pool thread. Create the delegate by passing your callback method to the WaitCallback constructor. Your method must have the signature shown here.

4.      Synchronize thread by events

We can use AutoResetEvent and ManualResetEvent to synchronize thread and allow threads to communicate with each other by signaling

AutoResetEvent and ManualResetEvent are very similar, for they have similar constructors and other member methods. Here are the constructors

public ManualResetEvent (

        bool initialState

)

public AutoResetEvent (

        bool initialState

)

Parameters

initialState

true to set the initial state signaled; false to set the initial state to nonsignaled.

 

The only difference is:

An AutoResetEvent object is automatically reset to non-signaled by the system after a single waiting thread has been released.

An ManualResetEvent object remains signaled until its Reset method is called.

That means if we use manualResetEvent.WaitOne() method, when after manualResetEvent.Set() is called, the signal keeps signaled until manualResetEvent.Reset() method is called; while for AutoResetEvent, after the waiting method is executed, it auto reset to be non-signaled

Here I searched an example to make as a demo:

using System;

using System.Threading;

 

namespace AutoResetEvent_Examples

{

    class MyMainClass

    {

        //the initial state is non-signaledso we use false as the parameter

        const int numIterations = 100; //to make you more clear about the running

        //static AutoResetEvent myResetEvent = new AutoResetEvent(false);

        static ManualResetEvent myResetEvent = new ManualResetEvent(false);

        static int number;

 

        static void Main()

        {

            //create and start a thread

            Thread myReaderThread = new Thread(new ThreadStart(MyReadThreadProc));

            myReaderThread.Name = "ReaderThread";

            myReaderThread.Start();

 

            for (int i = 1; i <= numIterations; i++)

            {

                Console.WriteLine("Writer thread writing value: {0}", i);

                number = i;

 

                //after the value is written, use set() to send out an signal

                myResetEvent.Set();

 

                Thread.Sleep(1000);

            }

          

            myReaderThread.Abort();

        }

 

        static void MyReadThreadProc()

        {

            while (true)

            {

                //before the data is filled, it would not be read out

                myResetEvent.WaitOne();

                Console.WriteLine("{0} reading value: {1}", Thread.CurrentThread.Name, number);

            }

        }

    }

}

Please change the comment line AutoResetEvent and ManualResetEvent to check the results

5.      Shared object’s coordinate access

When use multiple threads, we may need to coordinate access shared objects. Here we list several methods to solve that problem

·         Monitor Class

In System.Threading namespace there is a class named Monitor that can enable to synchronize access to objects that are shared by multiple code paths. We can acquire a monitor lock to an arbitrary object that needed to be protected.

First use Monitor.Enter(obj) to lock the objects, then we can deal with the objects after finished that use Monitor.Exit(obj) to release the lock

·         Interlocked Class

This class can help to increment and decrement shared integer variables and performs safe atomic assignments of shared objects safely from multiple threads.

Interlocked.Increment(ref i);

Interlocked.Decrement(ref i);

Interlocked.Exchang()

6.      Asynchronous Pattern

Asynchronous delegates allow you to call a synchronous method in an asynchronous manner. When you call a delegate synchronously, the Invoke method calls the target method directly on the current thread. If the compiler supports asynchronous delegates, it will generate the Invoke method and the BeginInvoke and EndInvoke methods. If the BeginInvoke method is called, the common language runtime (CLR) will queue the request and return immediately to the caller. The target method will be called on a thread from the thread pool. The original thread, which submitted the request, is free to continue executing in parallel with the target method, which is running on a thread pool thread. If a callback method has been specified in the call to the BeginInvoke method, the callback method is called when the target method returns. In the callback method, the EndInvoke method obtains the return value and any in/out parameters. If no callback method is specified when calling BeginInvoke, EndInvoke can be called from the thread that called BeginInvoke.

Example:

using System;

using System.Threading;

class MyMainClass

    {

        delegate string AsyCallDelegate(string str);

        static string AsyCallMethod(string str)

        {

 

            return "hello " + str;

        }

 

        static void Main()

        {

            AsyCallDelegate testdelegate = new AsyCallDelegate(AsyCallMethod);

            testdelegate.BeginInvoke("Jiansong",new AsyncCallback(endAsycallMethod), testdelegate);

            Thread.Sleep(5000);

        }

        static void endAsycallMethod(IAsyncResult result)

        {

 

            AsyCallDelegate a = result.AsyncState as AsyCallDelegate;

            string str=a.EndInvoke(result);

           

            Console.WriteLine(str);

        }

}

If we don't use the callback function in BeginInvoke() method, we should use IAsyncResult result= testdelegate.BeginInvoke("Jiansong",null, testdelegate);

That means the main thread can’t execute until the work thread complete, so we should use result.IsCompleted to check whether the work thread is completed. After conpleted, then call testdelegate.EndInvoke() method finish asynchronous call.

using System;

using System.Threading;

 

namespace AutoResetEvent_Examples

{

    class MyMainClass

    {

        delegate string AsyCallDelegate(string str);

        static string AsyCallMethod(string str)

        {

            Thread.Sleep(2000);

            return "hello " + str;

        }

 

        static void Main()

        {

            AsyCallDelegate testdelegate = new AsyCallDelegate(AsyCallMethod);

           IAsyncResult result= testdelegate.BeginInvoke("Jiansong",null, testdelegate);

           while (true)

           {

               if (result.IsCompleted)

                   break;

           }

           string a = testdelegate.EndInvoke(result);

           Console.WriteLine(a);

        }

    }

}

Note: this mechanism can be used to update data in UI, because UI can be better updated in main thread, while do that in work thread, there may be some mistakes

7.      Reference:

·         MSDN

·         NETWORK PROGRAMMING FOR THE MICROSOFT .NET FRAMEWORK

posted @ 2010-03-22 16:59  Jiansong  阅读(963)  评论(0)    收藏  举报