Using Synchronization Techniques and Thread Pooling In this demonstration, you will show students how to perform synchronization by using the C# lock keyword and manual synchronization
Trang 1Asynchronous Programming in NET 74
Lab 14: Working With Multithreaded
Applications 92
Review 108
Module 14 (Optional): Threading and
Asynchronous Programming
Trang 2Information in this document, including URL and other Internet Web site references, is subject to change without notice Unless otherwise noted, the example companies, organizations, products, domain names, e-mail addresses, logos, people, places, and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, e-mail address, logo, person, places or events is intended or should be inferred Complying with all applicable copyright laws is the responsibility of the user Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property
2001-2002 Microsoft Corporation All rights reserved
Microsoft, ActiveX, BizTalk, IntelliMirror, Jscript, MSDN, MS-DOS, MSN, PowerPoint, Visual Basic, Visual C++, Visual C#, Visual Studio, Win32, Windows, Windows Media, and Window NT are either registered trademarks or trademarks of Microsoft Corporation in the U.S.A and/or other countries
The names of actual companies and products mentioned herein may be the trademarks of their respective owners
Trang 3Instructor Notes Module 14
This module provides students with knowledge about the support that the Microsoft® NET Framework provides for working with multithreaded
applications and asynchronous programming
After completing this module, students will be able to:
! Create and manage threads
! Create thread-safe code
! Create and use timers
! Create threads using thread pools
! Create managed threads that interact well with COM components
! Create Microsoft Windows® Forms applications with background threads
! Make asynchronous calls using delegates
Materials and Preparation
This section provides the materials and preparation tasks that you need to teach this module
Required Materials
To teach this module, you need the Microsoft PowerPoint® file 2349B_14.ppt
Preparation Tasks
To prepare for this module:
! Read all of the materials for this module
! Practice the demonstrations
! Complete the lab
Presentation:
150 Minutes
Lab:
60 Minutes
Trang 4Demonstrations
This section provides demonstration procedures that will not fit in the margin notes or are not appropriate for the student notes
The code for each of the following demonstrations is contained in project
folders that are located in <install folder>\Democode\Mod14
Use the debugger to step through the code while you point out features and ask students what they think will happen next
Managing Threads
In this demonstration, you will show students how to create and manage threads
in the NET Framework by using some of the classes and methods that were covered in Using Threads in NET
The code for this demonstration is contained in one project and is located in
<install folder>\Democode\Mod14\Demo14.1
Interrupt and Abort
In this demonstration, you will show students how to terminate threads by using
the Thread.Interrupt and Thread.Abort methods
The code for this demonstration is contained in one project and is located in
The code for this demonstration is contained in one project and is located in
<install folder>\Democode\Mod14\Demo14.3
Using Synchronization Techniques and Thread Pooling
In this demonstration, you will show students how to perform synchronization
by using the C# lock keyword and manual synchronization primitives, and also
how to obtain multiple threads by using a thread pool
The code for this demonstration is contained in one project and is located in
<install folder>\Democode\Mod14\Demo14.4
Trang 5Windows Forms Threading
In this demonstration, you will show students how to use a background thread
in a Windows Forms application
The code for this demonstration is contained in one project and is located in
<install folder>\Democode\Mod14\Demo14.5
Asynchronous File Stream Read
In this demonstration, you will show students how to use synchronous and asynchronous read methods on a file stream For the asynchronous case, you will show four different ways to complete the operation: callback, poll, end method call, and wait with timeout
The code for this demonstration is contained in one project and is located in
Trang 6Module Strategy
Use the following strategy to present this module:
! Introduction to Threading Provide a general introduction to the concept of threads and discuss advantages and disadvantages of using them As a simple illustration of the concept of threading, use Microsoft Internet Explorer to show how you can still do work while waiting for a download operation to complete
Provide a high level overview of the System.Threading namespace and
introduce the asynchronous design pattern, which you will cover in more detail in Asynchronous Programming in NET
Explain how application domains play a key role in NET threading architecture
! Using Threads in NET
Focus on the classes in the System.Threading namespace that are used to
start, manage, and terminate threads
In addition to the preceding operations, discuss the role of managed thread local storage
! Thread Safety Focus on the issues that students may encounter in multithreaded programming from sharing data and resources between threads, as a result
of thread synchronization
Introduce strategies that the NET Framework provides for dealing with
synchronization, in particular classes and interfaces in System.Threading
! Special Thread Topics
Introduce the Thread.Timer class, which provides a mechanism for executing methods at specified intervals Explain how a TimerCallback delegate is used in conjunction with a Timer
Discuss the use of thread pools in making multiple threads operate more efficiently
Discuss how managed threads call into a COM object
Outline best practices for implementing thread-safe code
Trang 7! Asynchronous Programming in NET Provide a brief definition of the concept of asynchronous programming as the ability to issue method calls to other components, and to carry on with other work without waiting for the operation to complete
Introduce the asynchronous design pattern, and emphasize that one of its innovations is that the caller can decide whether a particular call should be asynchronous
Spend most of the time in this section on the Asynchronous File Stream Read Example In addition to the code on the slides and information in the Student Notes, there is an accompanying demonstration
Discuss the use of Asynchronous delegates to call a synchronous method in
an asynchronous manner
Play the Asynchronous Programming animation to illustrate the NET Framework common language runtime support for asynchronous programming using Delegate objects
Trang 9Overview
! Introduction to Threading
! Using Threads in NET
! Thread Safety
! Special Thread Topics
! Asynchronous Programming in NET
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
In this module, you will learn about the support that the Microsoft® NET Framework provides for working with multithreaded applications and asynchronous programming The common language runtime abstracts much of the threading support into classes that greatly simplify most threading tasks Even if you do not create your own threads explicitly, you need to understand how your code should handle multiple threads if it is run in a multithreaded environment
You will also learn how to handle thread synchronization to maintain application responsiveness and avoid potential data corruption and other problems
In the NET Framework, asynchronous programming is a feature that is supported by Remoting, Networking: HTTP, TCP, File I/O, ASP.NET, and Microsoft Message Queue Server (MSMQ) Because asynchronous programming is a core concept, the NET Framework provides a common design pattern for handling asynchronous execution This module introduces the NET Framework asynchronous Design Pattern and gives examples of its use After completing this module, you will be able to:
! Create and manage threads
! Create thread-safe code
! Create and use timers
! Create threads using thread pools
! Create managed threads that interact well with COM components
! Create Microsoft Windows® Forms applications with background threads
! Make asynchronous calls using delegates
In this module, you will learn
about the support that the
.NET Framework provides
for working with
multithreaded applications
and asynchronous
programming
Trang 10" Introduction to Threading
! Overview of Threads
! Overview of Support for Threading in NET
! Thread Architecture in NET
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
In this section, you will learn about the advantages and disadvantages of using threads and the support for threads that is provided by the NET Framework
In this section, you will learn
about the advantages and
disadvantages of using
threads and the support for
threads that is provided by
the NET Framework
Trang 11Overview of Threads
! Threads
# The basic unit to which an operating system allocates processor time
# Enable multiple activities to appear to occur simultaneously
! Advantages of using multiple threads
# Application does background processing while keeping the UI responsive
# Distinguish tasks of varying priority
# Communicate over a network, to a Web server, and to a database
! Potential disadvantages of using threads
# Diminished performance due to increased operating system overhead, for example, thread context switching
# Controlling code execution with many threads is complex, and can be a source of many difficult to find and fix bugs
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
Whether you are developing for computers with one processor or several, you want your application to provide the most responsive interaction with the user, even if the application is currently doing other work Using multiple threads of execution is one of the most powerful ways to keep your application responsive
to the user and at the same time make use of the processor in between or even during user events
Threads
Threads are the basic unit to which an operating system allocates processor time, and more than one thread can execute code inside a process Each thread maintains exception handlers, a scheduling priority, and a set of structures that the system uses to save the thread context until it is scheduled The thread context includes all of the information that the thread needs to smoothly resume execution, including the thread’s set of CPU registers and stack, in the address space of the thread’s host process
Operating systems use processes to separate the different applications that they are executing The NET Framework further subdivides an operating system process into lightweight, managed subprocesses, called application domains,
represented by System.AppDomain One or more managed threads, represented by System.Threading.Thread, can run in one or any number of
application domains within the same process A preemptive multitasking operating system allocates a processor time slice to each thread that it executes Because each time slice is small, multiple threads appear to execute at the same time
Topic Objective
To define threads in the
context of general
multitasking and state the
primary advantages and
disadvantages of using
threads
Lead-in
Whether you are developing
for computers with one
processor or several, you
want your application to
provide the most responsive
interaction with the user,
even if the application is
currently doing other work
Delivery Tip
You can quickly illustrate
how multiple threads are
used to create nonblocking
UI by running the Microsoft
Internet Explorer Web
browser Start the browser
and type a URL address or
click a link to a site that
takes some time to
download Show how you
can still interact with the
application during this
download operation, for
example, canceling the
current download by clicking
Stop
Trang 12Advantages of using multiple threads
Threads enable multiple activities to appear to occur simultaneously in an application For example, a user can edit a worksheet while another thread recalculates other parts of the worksheet within the same application Threading maintains the responsiveness of the user interface while background processing
is occurring Threads can be used to enable users to receive notification of a task’s progress, and even to cancel the task at any time
You can also use threads to distinguish tasks of varying priority For example, you can use a high-priority thread to manage time-critical tasks, and a low-priority thread to perform other tasks
Threads are also useful when an application must wait for an event, such as user input or a read from the network or from a file, before continuing to execute Multiple threads enable the processor to handle a separate task while waiting for the completion of the event
Potential disadvantages of using threads
In some circumstances, threading may cause application performance to degrade On a single-processor computer, a compute-bound task, such as calculating a series of values by using multiple threads, would be slower because of the overhead caused by thread-switching Keeping track of a large number of threads consumes significant processor time If there are too many threads, most of them will not make significant progress
Controlling code execution with many threads is complex, and can be a source
of many bugs You run the risk of data corruption or other problems, such as deadlocks and race conditions To protect an application’s data from possible corruption, you must ensure that access to shared data is properly synchronized For more information about deadlocks and race conditions, see Thread Safety in this module
While this module focuses on threading, there are other ways of achieving concurrency that include using multiple processes/AppDomains, messaging, and database stored procedures
Note
Trang 13Overview of Support for Threading in NET
! Basic thread namespace
# System.Threading
! Standard design pattern for asynchronous programming
the IAsyncResult interface
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
To provide support for multithreaded programming, the NET Framework supplies its own namespace for thread creation and management and a programming model to handle asynchronous operations
Basic thread namespace The System.Threading namespace provides classes and interfaces that enable multithreaded programming System.Threading includes classes that are used
to create and manage threads, protect shared data, and improve system responsiveness
The System.Threading.Thread class is an abstraction of a managed thread that
executes within the runtime This includes threads that are created by the runtime and those that are created outside the runtime but that interact with the runtime environment to execute some managed code
The System.Threading namespace includes classes that assist with thread
synchronization and protection of shared data For example, the
System.Threading.Interlocked class provides atomic operations for variables
that are shared by multiple threads The System.Threading.Monitor class
provides a synchronization mechanism to ensure that where multiple threads access a shared resource, only one thread can access the resource at a particular time
Topic Objective
To provide a high-level
overview of the
System.Threading
namespace and introduce
the asynchronous design
pattern
Lead-in
Before examining how
threads work in the NET
Framework, let’s briefly
review important ways in
which the NET Framework
provides support for
threading
Trang 14Standard design pattern for asynchronous programming
The standard asynchronous design pattern in the NET Framework provides an efficient model to manage asynchronous operations and provide a consistent programming model The NET Framework provides support for asynchronous
programming using the IAsyncResult interface and delegate classes that enable
a programmer to avoid some of the implementation details of threading The asynchronous design pattern is covered in more detail later in this module
For more information about the System.Threading namespace and its classes,
see System.Threading Namespace in the NET Framework SDK documentation
Trang 15Thread Architecture in NET
Example of a Process Hosting AppDomains
Shared Data Shared Data Shared Data
Thread Specific Data
Thread Specific Data
Thread Specific Data
Thread Specific Data
Thread Specific Data
Thread Specific Data
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
Application domains, also known as AppDomains, play a key role in how threads work in the NET Framework An application domain is a runtime representation of a logical process within a physical process A single process can contain multiple application domains, each of which is completely isolated from other application domains within this or any other process One or more threads run in an application domain
Although hosting threads within application domains is conceptually similar to the COM threading model with its use of apartments, there is an important difference: application domains are managed types whereas the COM threading model is built on an unmanaged architecture
For more information about application domains, see Module 2, “Introduction
to a Managed Execution Environment,” in Course 2349B, Programming with
the Microsoft NET Framework (Microsoft Visual C# NET)
Trang 16Mapping from Win32 Threading to Managed Threading
The following table maps Microsoft Win32® threading elements to their approximate runtime equivalent Note that this mapping does not represent
identical functionality For example, TerminateThread does not execute
finally clauses or free up resources, and cannot be prevented However, Thread.Abort executes all of your rollback code, reclaims all of the resources,
and can be denied by using ResetAbort Be sure to read the NET Framework
SDK closely before making assumptions about functionality
Thread.Start
SuspendThread Thread.Suspend ResumeThread Thread.Resume Sleep Thread.Sleep WaitForSingleObject on the thread handle Thread.Join
GetCurrentThread Thread.CurrentThread SetThreadPriority Thread.Priority
No equivalent Thread.Name
Close to CoInitializeEx (Ole32.dll) Thread.ApartmentState
Trang 17" Using Threads in NET
! Starting Threads
! Thread Properties and Parameters
! Managing Threads
! Thread Local Storage
! Interrupting and Terminating Threads
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
In this section you will learn how to start, manage, and terminate threads
The System.Threading namespace includes classes for starting managing, and
terminating threads
Being able to perform basic threading operations is only the first requirement in creating multithreaded applications On a more advanced level, you must consider issues of data protection and performance These issues are covered in the topic Thread Safety in this module
Having briefly reviewed how
an operating system uses
threads to perform
multitasking, let’s look at
how threading works in the
.NET Framework
Trang 18Starting Threads
! Create a new instance of a Thread Object
parameter
# ThreadStart references the method that will be
executed by the new thread
! Thread is not executed until the Thread.Start method is invoked
Thread t = newThread(new ThreadStart(MyClass.AStaticMethod));
t.Start();
Thread t = newThread(new ThreadStart(MyClass.AStaticMethod));
t.Start();
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
Creating a new instance of a Thread class creates a new managed thread The constructor for Thread takes, as its only parameter, a ThreadStart delegate that references the method that will be executed by the new thread The Thread function does not begin executing until the Start method is called
Topic Objective
To explain how to instantiate
and start a new thread by
using the NET Framework
classes
Lead-in
Creating a new instance of a
Thread class creates a new
managed thread
Trang 19The following code shows how to create and start new threads:
using System;
using System.Threading;
class MyClass {
//…
} } class App {
static void Main() {
// Create and start thread on an instance method MyClass aMyClass = new MyClass();
Thread t1 = new Thread(new ThreadStart(aMyClass.AnInstanceMethod)); t1.Start();
// Create and start thread on a static method Thread t2 = new
Thread(new ThreadStart(MyClass.AStaticMethod)); t2.Start();
//…
} }
In the preceding example, the calls to t1.Start and t2.Start place the t1 and t2
threads in the running state, and the operating system can schedule them for
execution The Start method submits an asynchronous request to the system,
and the call returns immediately, possibly before the new thread has started The thread’s execution begins at the first line of the method that is referred to
by the thread delegate Calling Start more than once on the same thread causes the runtime to throw a ThreadStateException
Trang 20Thread Properties and Parameters
! Use the Thread.Name and Thread.Priority properties to get or set the name and priority of the thread
! Designate a thread as a background or a foreground thread by setting the Thread.IsBackground property
execution environment alive
! Encapsulate thread parameters in an object
t.Name = "My Background Thread";
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
To get or set the name of a thread and its priority, use the Thread.Name and
Thread.Priority properties Thread.Priority gets or sets the following values
that indicate the scheduling priority of a thread:
To describe some key
Thread class properties and
how to pass parameters to
threads
Lead-in
To get or set the name of a
thread and its priority, use
the Thread.Name and
Thread.Priority properties
Note
Trang 21Background and Foreground Threads
A managed thread runs as a background thread or a foreground thread
Background threads are identical to foreground threads except that a background thread does not keep the managed execution environment alive After all foreground threads have been stopped in a managed process (where the exe file is a managed assembly), the system stops all background threads and shuts down You can designate a thread as a background or foreground
thread by setting the Thread.IsBackground property
For example, to designate a thread as a background thread, you set
Thread.IsBackground to true Likewise, to designate a thread as foreground
thread, set IsBackground to false
All threads that enter the managed execution environment from unmanaged code are marked as background threads All threads that are generated by
creating and starting a new Thread object are foreground threads If you create
a thread that you want to listen for some activity, such as a socket connection,
you should set Thread.IsBackground to true, so that your process can
terminate
For example, to set a thread t to be a background thread:
t.IsBackground = true;
Trang 22Encapsulating thread parameters in an object
It is sometimes important to supply parameters to a thread However, the
ThreadStart delegate takes as its only parameter a ThreadStart delegate The
following code demonstrates how to use an object to encapsulate thread parameters:
using System;
using System.Threading;
class MyClassWithThreadState {
// method can reference sleepTime Thread.Sleep(sleepTime);
} } class Class1 {
static void Main() {
int sleepTime = 1000; // time for the thread to sleep MyClassWithThreadState myClassWithThreadState = new MyClassWithThreadState(sleepTime);
Thread ts = new Thread(new ThreadStart(myClassWithThreadState.ThreadMethod)); ts.Start();
// … }
}
Trang 23Managing Threads
! Thread.Sleep causes the current thread to block
! Suspend and Resume methods are not generally useful
# Can result in serious application problems like deadlocks
! Thread.Join waits for another thread to stop
! Thread.WaitHandle methods wait for one or more events
! Thread.ThreadState property - bit mask of the thread's state
Thread.Sleep(3000); // blocks for 3 seconds
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
Typically, thread management includes tasks such as suspending a thread for a period of time, waiting until another thread completes, or waiting until one or more specific events occur
Pausing and Resuming Threads
After starting a thread, you sometimes need to pause that thread for a fixed
period of time Calling Thread.Sleep causes the current thread to immediately block for the number of milliseconds you pass to Sleep, yielding the remainder
of its time slice to another thread One thread cannot call Sleep on another
thread For example, to cause the current thread to suspend for three seconds,
call the static method of Thread.Sleep as follows:
Thread.Sleep(3000);
Calling Thread.Sleep(Timeout.Infinite) causes a thread to sleep until it is interrupted by another thread that calls Thread.Interrupt or is aborted by
Thread.Abort
Using Thread.Suspend to pause a thread
You can also pause a thread by calling Thread.Suspend When a thread calls
Thread.Suspend on itself, the call blocks until the thread is resumed by
another thread
When one thread calls Thread.Suspend on another thread, the call is a nonblocking call that causes the other thread to pause Calling Thread.Resume
breaks another thread out of the suspended state and causes the thread to resume
execution, regardless of how many times Thread.Suspend was called For example, if you call Thread.Suspend five consecutive times and then call
Thread.Resume, the thread resumes execution immediately following the call
to Resume
Topic Objective
To describe the classes that
the runtime uses to pause,
resume, and force threads
to wait
Lead-in
Let’s look at how the
runtime provides classes to
manage threads
Trang 24Unlike Thread.Sleep, Thread.Suspend does not cause a thread to immediately
stop execution The runtime must wait until the thread has reached a safe point before it can suspend the thread A thread cannot be suspended if it has not been started or if it has stopped
For more information about safe points, see the NET Framework SDK
The Suspend and Resume methods are not generally useful for applications,
and you should not confuse them with synchronization mechanisms Because
Suspend and Resume do not rely on the cooperation of the thread that is being
controlled, they are highly intrusive and can cause serious application problems For example, if you suspend a thread that holds a resource needed by another thread, this causes a deadlock condition
Some applications do need to control the priority of threads for better
performance To do this, you should use Thread.Priority rather than
Thread.Suspend in your application
Using Thread.Join to pause a thread
You can force a thread to wait for another thread to stop by calling
Thread.Join, as shown in the following code:
using System;
using System.Threading;
class MyApp {//…
static void MyThreadMethod() {
//…
} static void Main() {
// create, start and join a simple background thread // MyThreadMethod is the secondary thread's entry point Thread t = new Thread(new ThreadStart(MyThreadMethod)); // Start the thread
t.Start();
// Wait for the thread to exit t.Join();
} }
Trang 25Using the WaitHandle class to wait for events
You can force a thread to wait for one or more events to occur by calling
methods in the Thread.WaitHandle class
The following table describes some of the methods in the WaitHandle class Method Description
WaitAll This method waits for all of the elements in the specified array to
The WaitHandle class encapsulates Win32 synchronization handles While
WaitHandle objects represent operating system synchronization objects and
expose advanced functionality, they are less portable than the Monitor.Wait
method, which is fully managed and, in some circumstances, is more efficient
in its use of operating system resources
Using Classes that are derived from WaitHandle
Examples of classes that derive from WaitHandle include AutoResetEvent,
ManualResetEvent, and Mutex You use the AutoResetEvent class to make a
thread wait until some event puts it in the signaled state by calling
AutoResetEvent.Set Unlike ManualResetEvent, AutoResetEvent is
automatically reset to nonsignaled by the system after a single waiting thread has been released If no threads are waiting, the event object’s state remains
signaled The AutoResetEvent corresponds to a Win32 CreateEvent call,
false specified by the bManualReset argument
Trang 26For example, the following code shows how to force the main thread to wait until the threads that it has created signal that they have finished executing: using System;
using System.Threading;
class MyClassWithThreadState {
//…
done.Set(); // signal that we are finished }
} class MyApp {
ts = new Thread( new ThreadStart(myClassWithThreadState.ThreadMethod)); ts.Start();
} // Wait for all threads to indicate that they are done WaitHandle.WaitAll(waitEvents);
//…
} }
You can also use multiple calls to the Thread.Join method to wait for
multiple threads to exit
In this module, thread safety describes how to force a thread to wait for access
to a synchronized object, such as a Mutex method call
Also in this module, Terminating Threads describes how to interrupt a waiting
thread by calling the Thread.Interrupt or Thread.Abort method
Note
Trang 27Thread Activity States The Thread.ThreadState property provides a bit mask that indicates a thread’s
current state A thread is always in at least one of the possible states in the
ThreadState enumeration, and can be in multiple states at the same time
When you create a managed thread, it is in the Unstarted state, and remains in this state until it is moved into the started state by calling Thread.Start
Unmanaged threads that enter the managed environment are already in the started state
When in the started state, some actions can cause the thread to change states
The following table lists the actions that cause a change of state and the corresponding new state
Action ThreadState
A thread is created within the common language runtime Unstarted
The thread calls Wait on another object WaitSleepJoin
The thread calls Join on another thread WaitSleepJoin
The thread responds to a Suspend request Suspended
Because the Running state has a value of 0, you cannot perform a bit test to
discover this state Instead, you can use the following test (in pseudo-code):
if ((tState & (Unstarted | Stopped)) == 0) // implies Running Threads are often in more than one state at any particular time For example, if
a thread is blocked from a Wait call and another thread calls Abort on that same thread, the thread is in both the WaitSleepJoin and the AbortRequested
state at the same time In that case, as soon as the thread returns from the call to
Wait or is interrupted, it receives the ThreadAbortException
After a thread leaves the Unstarted state as the result of a call to Thread.Start,
it can never return to the Unstarted state A thread can never leave the Stopped
state, either
Trang 28Thread Local Storage
! Managed thread local storage - data unique to a thread
! Thread-Relative Static Fields
thread static variables are initialized to null
class AClassWithThreadState{
[ThreadStatic] public static int count = 42;
public void ThreadMethod() {
count++;
}}
class AClassWithThreadState{
[ThreadStatic] public static int count = 42;
public void ThreadMethod() {
count++;
}}
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
Managed thread local storage (TLS) provides dynamic data slots that are unique
to a thread and an application domain combination The two types of data slots are named slots and unnamed slots Named slots can be convenient, because you can use a mnemonic identifier But other components can intentionally or unintentionally modify a named slot by using the same name for the
component’s own thread-relative storage However, if you do not expose an unnamed data slot to other code, it cannot be used by any other component
To use managed TLS, create your data slot by using
Thread.AllocateNamedDataSlot or Thread.AllocateDataSlot, and use the
appropriate methods to set or retrieve the information that is placed there
Topic Objective
To show how to use
managed thread local
storage
Lead-in
Let’s discuss how to
manage thread local
storage
Trang 29Thread-Relative Static Fields
If you know that a field of your type should always be unique to a thread and application domain combination, decorate a static field with the
ThreadStaticAttribute attribute Any class constructor code runs on the first
thread in the first context that accesses the field In all other threads or contexts,
the field is initialized to null, or Nothing in Microsoft Visual Basic® Therefore, you should not rely on class constructors to initialize thread-relative static fields Instead, you should always assume that thread-relative static fields
are initialized to null
For example, the following code shows how to use thread relative static fields
to store a thread specific counter:
class AClassWithThreadState {
// NOTE: Only the first thread instance's field is // initialized, other threads have the field zeroed [ThreadStatic] public static int count = 42;
public void ThreadMethod() {
count++;
// … }
//…
}
Trang 30Demonstration: Managing Threads
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
This demonstration shows first how to create, manage, and join with a simple background thread Then a more complex example is shown where parameters and thread static values for a thread instance are encapsulated in a class,
MyClassWithThreadState After starting multiple threads, the main thread
calls the WaitHandle.WaitAll method to wait until all those threads indicate that they have finished executing by setting their AutoResetEvent objects
The code for this demonstration is located in <install folder>\Democode\
Mod14\Demo14.1
Topic Objective
To demonstrate how to
create and manage threads
in the NET Framework
Lead-in
In this demonstration, you
will see how to create and
manage threads in NET, by
using some of the classes
and methods that we have
talked about in this section
Delivery Tip
You should run this demo
with breakpoints set in the
Main, MyThreadMethod,
and
MyClassWithThreadState.
ThreadMethod methods
and observe the
Visual Studio NET
Threads window
To make the Visual Studio
.NET Threads window
visible, when the application
is running, on the Debug
menu, click Windows, and
then click Threads
Trang 31Interrupting and Terminating Threads
! Thread.Interrupt method
ThreadInterruptedException
! Thread.Abort method to permanently terminate thread
ThreadAbortException
# ThreadAbortException is a special exception that can
be caught by application code, but is rethrown at the end
of the catch block unless ResetAbort is called
Thread.Join to block until thread terminates
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
In addition to starting, pausing, and resuming threads, the NET Framework also provides classes for terminating threads
Thread.Interrupt wakes a thread from any wait state and causes a ThreadInterruptedException to be thrown in the destination thread
Thread.Abort is used to permanently terminate a thread
Using Thread.Interrupt When you call Thread.Interrupt, you wake a thread from any wait state and cause a ThreadInterruptedException to be thrown in the destination thread The thread should catch the ThreadInterruptedException and do whatever is
appropriate to continue working If the thread ignores the exception, the runtime catches the exception and stops the thread
For example, you may want to terminate a thread in response to a user-initiated
event, such as clicking a Cancel button The Cancel button’s event handler may run in one thread (thread1), while the event to which the Cancel action applies may run in a separate thread (thread2) In your event handler, you can call the
Interrupt method on the second thread, as follows:
// inside the Cancel button's event handler
if ( thread2 != null) {
thread2.Interrupt();
thread2 = null;
}
Topic Objective
To explain how to terminate
a thread by using the NET
Framework classes
Lead-in
Let’s look at how to
terminate a thread in the
.NET Framework
Trang 32Using Thread.Abort
To terminate a thread permanently, you use the Thread.Abort method When you call Abort to terminate a thread, the system wakes the thread from any wait state and throws a ThreadAbortException The runtime executes the catch block and any finally block
ThreadAbortException is a special exception that can be caught by
application code, but is rethrown at the end of the catch block unless
ResetAbort is called Only code with the proper permissions can call ResetAbort method ResetAbort cancels the request to abort, and prevents the ThreadAbortException from terminating the thread If the finally blocks
contain any unbounded computations, the thread’s termination may be delayed indefinitely
Because the call to Thread.Abort does not always result in the immediate
termination of a thread, you can ensure the thread’s destruction by calling the
Join method on the thread after you call Abort Join blocks the calling thread
until the thread stops executing
After a thread terminates, you cannot restart it by calling Start again For
example, if code creates a thread, lets it run, and then aborts the thread, any attempt to restart the thread causes the runtime to throw a
ThreadStateException
Blocking Issues
If a thread makes an unmanaged call into the operating system, and the system has blocked the thread in unmanaged code, the runtime will not take control of
the blocked thread for Thread.Interrupt or Thread.Abort
In the case of Thread.Abort, the runtime marks the thread for Abort and takes
control of the thread when it re-enters managed code Where possible, you
should use managed blocking rather than unmanaged blocking The following methods are all responsive to Thread.Interrupt and Thread.Abort:
Trang 33Demonstration: Interrupt and Abort
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
This demonstration shows how to use Thread.Interrupt and Thread.Abort to
terminate threads
Pay careful attention to what happens in the catch and finally blocks when the
Interrupt and Abort methods are called Notice whether the thread resumes
working after the method calls as indicated by the output string “Thread - still alive and working.”
Topic Objective
To demonstrate how to
terminate threads by using
the Thread.Interrupt and
Thread.Abort methods
Lead-in
In this demonstration, you
will see how to use the
Thread.Interrupt and
Thread.Abort methods to
terminate threads
Trang 34The following code is used in the demonstration:
using System;
using System.Threading;
public class ThreadWork {
static public bool resetAbort;
public static void DoWork() {
try { for(int i=0; i<100; i++)
Console.WriteLine(
"Thread - caught ThreadAbortException"); Console.WriteLine(
"Exception message: {0}", e.Message);
if (resetAbort == true) Thread.ResetAbort(); }
finally { Console.WriteLine("Thread - finally block"); }
(Code continued on the following page.)
Trang 35class ThreadAbortTest {
public static void Main() {
ThreadStart myThreadDelegate = new ThreadStart(ThreadWork.DoWork);
Thread myThread;
Console.WriteLine(
"Main - interrupting my thread.");
myThread = new Thread(myThreadDelegate);
Trang 36The output should be similar to the following:
Main - interrupting my thread
Thread - still alive and working
Thread - finished working
Main - aborting my thread with resetAbort: True Thread - working
Thread - caught ThreadAbortException Exception message: Thread was being aborted Thread - finally block
Thread - still alive and working
Thread - finished working
Main - aborting my thread with resetAbort: False Thread - working
Thread - caught ThreadAbortException Exception message: Thread was being aborted Thread - finally block
Main ending
Trang 37! Thread Safety and the Net Framework Classes
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
The System.Threading namespace provides classes and interfaces that enable
multithreaded programming This namespace includes classes for synchronizing access to data to provide thread safety
This section focuses on the issues that you may encounter from sharing data and resources between threads in multithreaded programming The section also introduces NET Framework synchronization strategies
In this section, we’ll look at
the importance of thread
safety and the mechanisms
that the NET Framework
supports to provide thread
safety
Trang 38Overview of Thread Safety
! Common problems sharing data and resources between threads:
# Race condition – uncontrolled order of execution causing errors
# Deadlocks – threads waiting for each other so that they cannot proceed
! Best approach is to avoid sharing when possible
# Encapsulate data into instances that are not shared across requests
! The NET Framework provides three strategies to synchronize access to instance and static methods and instance fields:
# Synchronized contexts
# Synchronized code regions
# Manual synchronization
***************************** ILLEGAL FOR NON - TRAINER USE ******************************
When writing multithreaded applications, you may encounter common
problems, such as race conditions and deadlock
Race condition
Two or more threads that simultaneously access the same data can cause undesirable and unpredictable results For example, one thread may update the contents of a structure while another thread reads the contents of the same structure In this scenario, it is unknown what data the reading thread will receive: the old data, the newly written data, or possibly a mixture of both When the proper operation of a program depends on the uncontrolled order of execution of multiple threads, then a race condition exists
Deadlock
A multithreaded application can also encounter problems with thread synchronization if multiple threads are waiting for each other to release resources This blocking of thread execution is known as a deadlock
For example, consider two threads that transfer money between accounts A and
B The first thread, Thread 1, is coded to do the following tasks in the following order:
! Wait for and acquire a lock on account A
! Wait for and acquire a lock on account B
! Transfer funds
! Release both locks The second thread, Thread 2, is coded in the same way, except that it first acquires a lock on account B, then on account A
Topic Objective
To discuss problems that
result from sharing data and
resources between threads,
and to introduce NET
Framework synchronization
strategies
Lead-in
Let’s talk about how sharing
data and resources between
threads can lead to
compromised thread safety
Trang 39Consider the case where Thread 1 acquires lock A, but before it can acquire lock B, Thread 2 runs and acquires lock B In this case, both threads block while waiting for the other lock Because both threads are blocked, neither thread releases the lock that is required by the other thread to proceed This condition is referred to as a deadlock situation
You can best achieve thread safety by not sharing data or resources between threads If possible, use a design pattern that encapsulates data and resources into instances that are not shared across requests When this is not possible you should use the NET Framework thread synchronization classes to provide thread safety
.NET Framework strategies for synchronization
When you need to share data, the NET Framework provides three strategies to synchronize access to instance methods, static methods, and instance fields:
! Synchronized contexts
You can use the SynchronizationAttribute attribute to enable simple, automatic synchronization for ContextBoundObject objects
! Synchronized code regions
You can use the MethodImplAttribute class (passing
MethodImplOptions.Synchronized), the Monitor class, or compiler
support to synchronize only the code blocks that need it
No Synchronization
No synchronization support is the default for objects Any thread can access any method or field at any time
Synchronized Context
You can use the SynchronizationAttribute on any class that is derived from
ContextBoundObject to synchronize all instance methods and fields All
objects in the same context domain share the same lock Multiple threads are allowed to access the instance methods and fields, but only a single thread is allowed at any one time Static members are not protected from concurrent access by multiple threads
The following table shows the support provided for fields and methods under the synchronization context category
Synchronization context supports Synchronization context does not support
Instance fields and instance methods Global fields, static fields, and static methods
Specific code blocks
Trang 40Synchronized Code Regions
You can use the Monitor class or a compiler keyword to synchronize blocks of
code, instance methods, and static methods In Microsoft Visual C#™, the
keyword is lock You can also decorate a method with a MethodImplAttribute
(passing MethodImplOptions.Synchronized), which has a similar result to
using Monitor or one of the compiler keywords for a Monitor code block
where the code block is the entire method
The following table shows the support provided for fields and methods under the synchronized code regions category
Synchronized code regions supports (only if marked) Synchronized code regions does not support
Static methods, instance methods, and specific code blocks
Global fields, static fields, and instance fields