Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

C# ПІДРУЧНИКИ / c# / MS Press - Msdn Training Programming Net Framework With C#

.pdf
Скачиваний:
193
Добавлен:
12.02.2016
Размер:
16.87 Mб
Скачать

Module 14 (Optional): Threading and Asynchronous Programming

53

 

 

 

The following example shows how to use a timer and a delegate to execute methods at specified intervals of two seconds:

using System;

using System.Threading;

class App {

public static void Main() { Console.WriteLine(

"Checking for status updates every 2 seconds."); Console.WriteLine(

"(Hit Enter to terminate the sample)");

Timer timer = new Timer(new TimerCallback(CheckStatus), null, 0, 2000);

Console.ReadLine();

timer.Dispose();

}

//The callback method's signature MUST

//match that of a System.Threading.TimerCallback

//delegate (it takes an Object parameter and returns void) static void CheckStatus(Object state) {

Console.WriteLine("Checking Status."); // ...

}

}

54

Module 14 (Optional): Threading and Asynchronous Programming

Thread Pools

Topic Objective

To introduce thread pooling.

Lead-in

You can often use thread pooling to make the use of multiple threads more efficient.

!Thread pooling is used to improve efficiency

#System optimizes based on all of computer’s processes

!Do not use thread pooling when you

#Need a task to have a particular priority

#Have a task that might run for a long time

#Need to place threads into a single-threaded apartment

#Need a stable identity to be associated with the thread

!IOCompletionCallback delegate for asynchronous I/O completion events

#A thread from the thread pool will process data when received

*****************************ILLEGAL FOR NON-TRAINER USE******************************

You can often use thread pooling to make the use multiple threads more efficient. Many applications use multiple threads, but often those threads spend a great deal of time in the sleeping state waiting for an event to occur. Other threads may enter a sleeping state and be awakened only periodically to poll for a change or update status information before going to sleep again.

Advantages of thread pools

Using thread pooling provides your application with a pool of worker threads that are managed by the system, allowing you to concentrate on application tasks rather than thread management. In fact, if you have a number of short tasks that require more than one thread, using the ThreadPool class is the easiest and typically the most efficient way to take advantage of multiple threads.

Thread pooling enables the system to optimize the use of multiple threads for better throughput, not only for your application’s process but also with respect to other processes on the computer. This optimization is transparent to your application. When you use a thread pool, the system can optimize thread time slices, taking into account all of the current processes on your computer.

Module 14 (Optional): Threading and Asynchronous Programming

55

 

 

 

Using thread pools in the .NET Framework

The .NET Framework uses thread pools for several purposes: asynchronous calls, System.Net socket connections, asynchronous I/O completion, timers, and registered wait operations, among others.

To use a thread pool, call ThreadPool.QueueUserWorkItem from managed code, or CorQueueUserWorkItem from unmanaged code, and pass a WaitCallback delegate that wraps the method that you want to add to the queue.

You can also queue work items that need to be executed when a wait operation completes. You queue these work items by using

ThreadPool.RegisterWaitForSingleObject and passing a WaitHandle and a

WaitOrTimerCallback delegate. When the WaitHandle is signaled or when timed out, it raises a call to the method wrapped by the WaitOrTimerCallback delegate. In both cases the thread pool uses or creates a background thread to invoke the callback method.

Reasons Not to Use Thread Pools

There are several scenarios in which it is appropriate to create and manage your own threads instead of using the ThreadPool class. You should do so when:

!

!

!

You need a task to have a particular priority.

You have a task that may run a long time and, therefore, block other tasks.

You need to place threads into a single-threaded apartment (all ThreadPool threads are in the multithreaded apartment).

!You need a stable identity to be associated with a particular thread. For example, you may want to use a dedicated thread to abort that thread, suspend it, or discover it by name.

56

Module 14 (Optional): Threading and Asynchronous Programming

The following example shows one way to use the ThreadPool class methods to start multiple threads and monitor their completion:

using System;

using System.Threading;

class Counter

{

public void Read(int threadNum)

{

//…

}

public void Increment(int threadNum)

{

//…

}

}

class App

{

static Counter counter = null;

static int totalNumberOfAsyncOps = 10;

static int numAsyncOps = totalNumberOfAsyncOps; static AutoResetEvent asyncOpsAreDone =

new AutoResetEvent(false);

public static void Main()

{

counter = new Counter(); for (int threadNum = 0;

threadNum < totalNumberOfAsyncOps; threadNum++)

{

ThreadPool.QueueUserWorkItem(

new WaitCallback(UpdateResource), threadNum);

}

asyncOpsAreDone.WaitOne();

}

//…

//The callback method's signature MUST match that of a

//System.Threading.TimerCallback delegate

//(it takes an Object parameter and returns void) static void UpdateResource(Object state)

{

int threadNum = (int) state;

if ((threadNum % 2) != 0) counter.Read(threadNum); else counter.Increment(threadNum);

if (( Interlocked.Decrement(ref numAsyncOps)) == 0) asyncOpsAreDone.Set();

}

}

Module 14 (Optional): Threading and Asynchronous Programming

57

 

 

 

IOCompletionCallback

Using asynchronous I/O completion events, a thread from the thread pool processes data only when the data is received. After the data has been processed, the thread returns to the thread pool.

To make an asynchronous I/O call, you must associate an operating system I/O handle with the thread pool and specify a callback method. When the I/O operation completes, a thread from the thread pool invokes the callback method. For more information about using asynchronous I/O completion events, see the

.NET Framework SDK documentation.

58

Module 14 (Optional): Threading and Asynchronous Programming

Demonstration: Using Synchronization Techniques and Thread

Pooling

Topic Objective

To demonstrate various synchronization techniques and the use of the thread pool.

Lead-in

In this demonstration, we’ll look at various synchronization techniques and the use of the thread pool.

*****************************ILLEGAL FOR NON-TRAINER USE******************************

This demonstration shows how to perform synchronization using the C# lock keyword and manual synchronization primitives and how to use the thread pool to obtain multiple threads. The demonstration consists of several test sequences, which are described in this topic.

The classes in the demonstration derive from the class Counter and differ by the technique for synchronization that they implement. For each class’s test, the even number threads execute the class’s Read method, which simply examines and outputs the counter’s value, but does not modify it. The odd number threads execute the class’s Write method, which reads the counter, increments the value, and stores the new value back in the counter.

The code for this demonstration is located in <install folder>\Democode\

Mod14\Demo14.4.

Module 14 (Optional): Threading and Asynchronous Programming

59

 

 

 

The Unsafe test

The Unsafe test uses an instance of the CounterUnsafe class which does no synchronization. As a result of the race condition, the five Write method invocations fail to increase the value of count by 5.

The test results in output that is similar to the following:

Unsafe test:

 

Start Resource writing

(Thread=0) count: 0

Start Resource reading

(Thread=1)count: 0

Stop

Resource reading

(Thread=1) count: 0

Start Resource writing

(Thread=2) count: 0

Start Resource reading

(Thread=3)count: 0

Stop

Resource writing

(Thread=0) count: 1

Start Resource writing

(Thread=4) count: 1

Stop

Resource reading

(Thread=3) count: 1

Start Resource reading

(Thread=5)count: 1

Stop

Resource reading

(Thread=5) count: 1

Start Resource writing

(Thread=6) count: 1

Start Resource reading

(Thread=7)count: 1

Stop

Resource reading

(Thread=7) count: 1

Start Resource writing

(Thread=8) count: 1

Stop

Resource writing

(Thread=2) count: 1

Start Resource reading

(Thread=9)count: 1

Stop

Resource reading

(Thread=9) count: 1

Stop

Resource writing

(Thread=4) count: 2

Stop

Resource writing

(Thread=6) count: 2

Stop

Resource writing

(Thread=8) count: 2

All Unsafe threads have completed.

60

Module 14 (Optional): Threading and Asynchronous Programming

The Interlocked test

The Interlocked test uses an instance of the CounterUsingInterlocked class, which uses an Interlocked.Increment instruction to atomically update the count. The five Write method invocations now increment count by 5.

The test results in output that is similar to the following:

Interlocked test:

Start Resource writing (Thread=0) count: 0

Stop Resource writing (Thread=0) count: 1

Start Resource reading (Thread=1)count: 1

Start Resource writing (Thread=2) count: 1

Stop Resource writing (Thread=2) count: 2

Start Resource reading (Thread=5)count: 2

Start Resource reading (Thread=3)count: 2

Start Resource writing (Thread=4) count: 2

Stop Resource writing (Thread=4) count: 3

Start Resource writing (Thread=6) count: 3

Stop Resource writing (Thread=6) count: 4

Start Resource reading (Thread=7)count: 4

Start Resource writing (Thread=8) count: 4

Stop Resource writing (Thread=8) count: 5

Start Resource reading

(Thread=9)count: 5

Stop

Resource reading

(Thread=1) count: 5

Stop

Resource reading

(Thread=5) count: 5

Stop

Resource reading

(Thread=3) count: 5

Stop

Resource reading

(Thread=7) count: 5

Stop

Resource reading

(Thread=9) count: 5

All Interlocked threads have completed.

Note In the preceding example, the Interlock.Increment method synchronized the concurrent thread’s Write method updates the count. However, this approach does not prevent the value of count from changing its value during another thread’s execution of the Read method. The manual synchronization techniques that are demonstrated in the remaining test sequences will synchronize execution to provide a consistent value for count during each Read operation.

Module 14 (Optional): Threading and Asynchronous Programming

61

 

 

 

The Lock test

The Lock test uses an instance of the CounterUsingLock class, which uses the Visual C# lock keyword to synchronize access to the object so that only one thread at a time executes either of the instance methods. The five Write method invocations now increment count by 5, and all of the Read operations have a consistent value for count.

The test results in output that is similar to the following:

Lock test:

Start Resource writing (Thread=0) count: 0

Stop Resource writing (Thread=0) count: 1

Start Resource writing (Thread=6) count: 1

Stop Resource writing (Thread=6) count: 2

Start Resource reading (Thread=9)count: 2

Stop Resource reading (Thread=9) count: 2

Start Resource reading (Thread=7)count: 2

Stop Resource reading (Thread=7) count: 2

Start Resource writing (Thread=4) count: 2

Stop Resource writing (Thread=4) count: 3

Start Resource writing (Thread=2) count: 3

Stop Resource writing (Thread=2) count: 4

Start Resource reading (Thread=3)count: 4

Stop Resource reading (Thread=3) count: 4

Start Resource reading (Thread=1)count: 4

Stop Resource reading (Thread=1) count: 4

Start Resource reading (Thread=5)count: 4

Stop Resource reading (Thread=5) count: 4

Start Resource writing (Thread=8) count: 4

Stop Resource writing (Thread=8) count: 5

All Lock threads have completed.

62

Module 14 (Optional): Threading and Asynchronous Programming

The Mutex test

The Mutex test uses an instance of the CounterUsingMutex class, with the Mutex class to synchronize access to the object so that only one thread at a time executes either of the instance methods. The five Write method calls now increment count by 5, and all the Read operations have a consistent value for count.

The test results in output that is similar to the following:

Mutex test:

Start Resource writing (Thread=0) count: 0

Stop Resource writing (Thread=0) count: 1

Start Resource reading (Thread=3)count: 1

Stop Resource reading (Thread=3) count: 1

Start Resource writing (Thread=4) count: 1

Stop Resource writing (Thread=4) count: 2

Start Resource reading (Thread=5)count: 2

Stop Resource reading (Thread=5) count: 2

Start Resource writing (Thread=6) count: 2

Stop Resource writing (Thread=6) count: 3

Start Resource reading (Thread=7)count: 3

Stop Resource reading (Thread=7) count: 3

Start Resource writing (Thread=8) count: 3

Stop Resource writing (Thread=8) count: 4

Start Resource writing (Thread=2) count: 4

Stop Resource writing (Thread=2) count: 5

Start Resource reading (Thread=1)count: 5

Stop Resource reading (Thread=1) count: 5

Start Resource reading (Thread=9)count: 5

Stop Resource reading (Thread=9) count: 5

All Mutex threads have completed.

Соседние файлы в папке c#