multithreading in.net 2.0 neal s. buchalter nsb consulting [email protected]

43
MultiThreading in .NET 2.0 Neal S. Buchalter NSB Consulting [email protected] www.NealBuchalter.com

Upload: myles-hart

Post on 30-Dec-2015

218 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

MultiThreading in .NET 2.0

Neal S. BuchalterNSB Consulting

[email protected]

Page 2: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 2

Why MultiThread?

• To keep the UI responsive.See “MultiThreadingDemo” code example.

• To improve performance (for example, concurrent operation of CPU bound and I/O bound activities).

• Design logic (for example, to model independent real-world objects).

Page 3: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 3

Why not MultiThread?

• Overhead can reduce actual performance.

• Complicates code, increases design time and risk of bugs.

Page 4: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 4

Some Definitions

• Threads are the basic units to which an operating system allocates processor time.

• Processes separate the different applications that the OS is executing.

• Application Domains are lightweight managed subprocesses into which the .NET Framework further subdivides an operating system process.

Page 5: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 5

Looking Ahead: Ways to MultiTask

• Run Multiple Applications

• Asynchronous File I/O

• Timers

• Run Multiple Threads

Page 6: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 6

Run Multiple Applications

…on multiple computers,…with multiple users.

Page 7: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 7

Asynchronous File I/O

• In normal (“synchronous”) file I/O, your code is blocked until the I/O is complete.

• With Asynchronous I/O, your main thread can continue doing other work while the I/O operation is being processed.

• Example: the System.IO.Stream class provides the asynchronous BeginRead, BeginWrite, EndRead and EndWrite methods, plus the ability to specify an AsyncCallback routine.

Page 8: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 8

Asynchronous File I/O, cont’d

Main Thread Other Thread

IAsyncResult ar = BeginRead(…)

Other work…

EndRead( ar )

Read file…

Page 9: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 9

Timers

.NET Provides three types of timers:

• Windows Timer:– Raises events on the UI thread.– Available on the Windows Forms tab of the Toolbox.

• Server Timer:– Raises events on a Thread Pool thread.– Available on the Components tab of the Toolbox.

• Thread Timer:– Makes callbacks on a Thread Pool thread.– Only available programmatically.

Page 10: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 10

Windows Timer• The Windows timer (System.Windows.Forms.Timer) is a Windows Forms control

designed for a single-threaded environment where UI threads are used to perform processing. It has an "Interval" property and a "Tick" event.

• The "Interval" property has a few limitations to consider when you are programming a Timer component:

– If your application or another application is making heavy demands on the system — such as long loops, intensive calculations, or drive, network, or port access — your application may not get timer events as often as the "Interval" property specifies.

– The interval can be between 1 and 64,767, inclusive, which means that even the longest interval will not be much longer than one minute (about 64.8 seconds).

– The interval is not guaranteed to elapse exactly on time. To ensure accuracy, the timer should check the system clock as needed, rather than try to keep track of accumulated time internally.

– The system generates 18 clock ticks per second — so even though the "Interval" property is measured in milliseconds, the true precision of an interval is no more than one-eighteenth of a second (approximately 55 milliseconds).

Page 11: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 11

Server Timer

• The server-based timer (System.Timers.Timer) is designed for use with worker threads in a multithreaded environment.

• The "Interval" property is a double (double-precision floating point), and therefore is effectively unlimited. The timer can be set for single‑shot or auto‑repeating operation.

• The "Elapsed" event defaults to the Thread Pool, but can be assigned to a UI thread.

Page 12: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 12

Thread Timer

• The thread timer (System.Threading.Timer) is a simple, lightweight timer that uses callback methods and is served by Thread Pool threads.

• The thread timer’s "Interval" property is a long (64-bit integer), and therefore is effectively unlimited.

Page 13: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 13

Looking Ahead: Threads

• Background versus Foreground

• Thread States

• Thread Class

• BackgroundWorker class

• Thread Pool

• Per Thread Data

• Modifying the UI

• Thread Synchronization

Page 14: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 14

Background Threads

• In .NET, a managed thread is either a background thread or a foreground thread.

• Background threads are identical to foreground threads with one exception: a background thread does not keep the managed execution environment running.

• Use the Thread.IsBackground property to determine whether a thread is a background or a foreground thread, or to change its status.

Page 15: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 15

Thread States

• The ThreadState enumeration has a FlagsAttribute attribute that allows a bitwise combination of its member values: Aborted, AbortRequested, Background, Running, Stopped, StopRequested, Suspended, SuspendRequested, Unstarted, WaitSleepJoin.

• Once a thread is created, it is in at least one of the states until it terminates. Threads created within the CLR are initially in the Unstarted state, while external threads that come into the runtime are already in the Running state. An Unstarted thread is transitioned into the Running state by calling Start.

Page 16: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 16

Thread Class

• You can create your own Thread object, or “borrow” one from the Thread Pool.

• Properties:IsAlive, IsBackground, IsThreadPool, ManagedThreadId, Name, Priority, ThreadState.

• Methods:Abort, Interrupt, Join, ResetAbort, Resume, Sleep, Suspend.

Page 17: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 17

Thread Class (cont’d)

• Creating a new Thread object creates a new managed thread. The Thread class has constructors that take a ThreadStart delegate or a ParameterizedThreadStart delegate; the delegate wraps the method that the new thread will invoke when you call its Start method.

• Using the ParameterizedThreadStart delegate is not a type-safe way to pass data, because the System.Threading.Thread.Start(System.Object) method overload accepts any object. An alternative is to encapsulate the thread procedure and the data in a helper class and use the ThreadStart delegate to execute the thread procedure.

Page 18: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 18

BackgroundWorker Class

• New in .NET 2.0

• Designed to simplify management of asynchronous operations for Windows Forms applications.

• Automatically marshals communications between the UI and Thread Pool threads.

• See “FibonacciCalculator” code example.

Page 19: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 19

BackgroundWorker Class (cont’d)

• Properties:CancellationPending, IsBusy, WorkerReportsProgress, WorkerSupportsCancellation

• Methods:CancelAsync, Reportprogress, RunWorkerAsync

• Events:DoWork, ProgressChanged, RunWorkerCompleted

• Note: the ProgressChanged and RunWorkerCompleted events internally implement the ISynchronizeInvoke interface (i.e. BeginInvoke…).

Page 20: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 20

Thread Pool

• The thread pool provides your application with a pool of worker threads that are managed by the system.

• The threads in the managed thread pool are background threads. A ThreadPool thread will not keep an application running after all foreground threads have exited.

• To request that a work item be handled by a thread in the thread pool, call the QueueUserWorkItem method. This method takes as a parameter a reference to the method or delegate that will be called by the thread pool thread. There is no way to cancel a work item after it has been queued.

• There is one thread pool per process. The thread pool has a default size of 25 threads per available processor. The number of threads in the pool can be changed by the SetMaxThreads method. Each thread uses the default stack size and runs at the default priority.

Page 21: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 21

Thread Pool (cont’d)

• There are several scenarios in which it is appropriate to create and manage your own threads instead of using thread pool threads: – You require a foreground thread.– You require a thread to have a particular priority.– You have tasks that cause the thread to block for long periods of

time. The thread pool has a maximum number of threads, so a large number of blocked thread pool threads might prevent tasks from starting.

– You need to place threads into a single-threaded apartment. (All thread pool threads are in the multithreaded apartment.)

– You need to have a stable identity associated with the thread, or to dedicate a thread to a task.

Page 22: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 22

Thread Local storage

• The CLR allocates a multi-slot data store array to each process when it is created. The thread can allocate a data slot in the data store, store and retrieve a data value in the slot, and free the slot for reuse after the thread expires. Data slots are unique per thread. No other thread (not even a child thread) can get that data.

• The AllocateDataSlot & AllocateNamedDataSlot static methods of the Thread class are used to allocate slots.

• Named slots can be found with GetNamedDataSlot.

• Named slots can be freed with FreeNamedDataSlot.

Page 23: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 23

Thread‑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.

• In all threads other than the first, the fields will be initialized to null if they are reference types, or to their default values if they are value types. As a result, you should not rely on class constructors to initialize thread-relative static fields. Instead, you always assume that thread-relative static fields are initialized to null or to their default values.

Page 24: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 24

Modifying the UI

• Most methods on a control can only be called from the thread where the control was created.

• In addition to the InvokeRequired property, there are only four methods on a control that are thread safe: Invoke, BeginInvoke, EndInvoke, and CreateGraphics.

• For all other method calls, you should use one of the invoke methods to marshal the call to the control's thread. The invoke methods always invoke their callbacks on the control's thread.

Page 25: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 25

Looking Ahead: Synchronization

• Interlocked

• Monitor

• Reader-Writer Lock

• Semaphore

• Mutex

Page 26: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 26

Interlocked

• Native to the Windows operating system, interlocked operations are extremely fast.

• Increment, Decrement, Add*, Read*, Exchange**, CompareExchange**

* New in .NET version 2.0** Additional overloads added in 2.0

Page 27: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 27

Interlocked (cont’d)

• Exchange:arg1 = arg2;return originalValueOfArg1;

• CompareExchange:If (arg1 equals arg3) arg1 = arg2;return originalValueOfArg1;

Page 28: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 28

Monitor

• Take and release a lock on a particular object using the Enter, TryEnter, and Exit methods.

• Wait releases the lock and waits (in the wait queue) to be notified. When Wait is notified, it returns and obtains the lock again.

• Both Pulse and PulseAll notify for the next thread in the wait queue to proceed.

• See “MonitorDemo” code example.

Page 29: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 29

Monitor (cont’d)

• The C# “lock” keyword is implemented with Monitor.

The following:lock(obj) { DoSomething(); }

Is equivalent to:System.Threading.Monitor.Enter(obj);try { DoSomething(); }finally { System.Threading.Monitor.Exit(obj); }

Page 30: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 30

Monitor (cont’d)

• The VB “SyncLock” Keyword is implemented with the Monitor class.

The following:SyncLock(obj) DoSomething()End SyncLock

Is equivalent to:Try System.Threading.Monitor.Enter(obj)

DoSomething()Finally System.Threading.Monitor.Exit(obj)End Try

Page 31: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 31

Reader-Writer Lock

• Lock can be acquired by an unlimited number of concurrent readers, or exclusively by a single writer.

• Can provide better performance than a Monitor if most accesses are reads, while writes are infrequent and of short duration.

• See “ReaderWriterLock” code example.

Page 32: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 32

WaitHandle

• Monitor objects are purely managed, fully portable, and might be more efficient in terms of operating-system resource requirements.

• WaitHandle objects represent operating-system waitable objects, are useful for synchronizing between managed and unmanaged code, and expose some advanced operating-system features like the ability to wait on many objects at once.

Page 33: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 33

Semaphore

• Semaphores maintain a count which can be used to control access to a pool of resources.

• The WaitOne call decrements the semaphore count when access is granted. A thread blocks if it requests entry when the count is zero.

• If a thread calls WaitOne multiple times, it must then either: call Release the same number of times, or call the Release method overload and specify the number of entries to be released.

Page 34: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 34

Semaphore (cont’d)

• The Semaphore class does not enforce thread affinity on calls to WaitOne and Release.

• For example, a common usage scenario for semaphores involves a producer thread and a consumer thread; with one thread always incrementing the semaphore count and the other always decrementing it.

• There is no guaranteed order (such as FIFO or LIFO) for blocked threads to enter the semaphore.

Page 35: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 35

Mutex

• A thread acquires a Mutex by calling WaitOne, and releases it by calling ReleaseMutex. Mutexes have thread affinity; that is, the mutex can be released only by the thread that owns it.

• Because the Mutex class derives from WaitHandle, you can also call the static WaitAll or WaitAny methods of WaitHandle to request ownership of a Mutex in combination with other wait handles.

Page 36: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 36

Mutex (cont’d)

• Mutexes are of two types: local mutexes and named system mutexes. Named system mutexes are visible throughout the operating system and can be used to synchronize the activities of multiple processes.

• You can create multiple .NET Mutex objects that represent the same named operating system mutex, and you can use the OpenExisting method to open an existing named system mutex.

• A local mutex exists only within your process. It can be used by any thread in your process that has a reference to the local Mutex object. Each Mutex object is a separate local mutex.

Page 37: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 37

Mutex (cont’d)

• If a thread terminates without releasing a Mutex, the mutex is said to be abandoned.

• In .NET 2.0, an AbandonedMutexException is thrown in the next thread that acquires the mutex.

• In .NET 1.0 and 1.1, an abandoned Mutex is set to the signaled state and the next waiting thread gets ownership. No exception is thrown.

Page 38: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 38

Looking Ahead: Nightmares

• Deadlocks

• Race Conditions

• Exception Handling

Page 39: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 39

Deadlocks

• A deadlock occurs when each of two threads tries to lock a resource the other has already locked. Neither thread can make any further progress.

• Some Techniques to Avoid Deadlocks:– Use time-outs on all attempts to acquire a lock.– Always acquire locks in the same order– WaitHandle.WaitAll()

Page 40: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 40

Race Conditions

• A race condition is a bug that occurs when the outcome of a program depends on which of two or more threads reaches a particular block of code first. Running the program many times produces different results, and the result of any given run cannot be predicted.

• Related terms: collision, small timing window.

Page 41: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 41

Exception Handling

• “If the thread method completes its execution, .NET will shutdown the thread gracefully. However, any unhandled exception thrown on the call stack of the thread will terminate not just the thread but also trigger shutdown of the hosting process itself. The one exception to this rule is the ThreadAbortException, which will only terminate the aborted thread. This behavior is a breaking change introduced by .NET 2.0. In contrast, .NET 1.1 will only terminate the thread that encountered the unhandled exception. When porting .NET 1.1 applications to .NET 2.0, make sure that your thread methods always catch and handle any exception, otherwise you risk unplanned application termination.”

Programming .NET Components, by Juval Löwy

Page 42: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 42

Exception Handling (cont’d)• “Exposing Threading Problems During Development

When threads are allowed to fail silently, without terminating the application, serious programming problems can go undetected. This is a particular problem for services and other applications which run for extended periods. As threads fail, program state gradually becomes corrupted. Application performance may degrade, or the application might hang.

Allowing unhandled exceptions in threads to proceed naturally, until the operating system terminates the program, exposes such problems during development and testing. Error reports on program terminations support debugging.

• Change from Previous Versions

The most significant change pertains to managed threads. In the .NET Framework versions 1.0 and 1.1, the common language runtime provides a backstop for unhandled exceptions in the following situations:

– There is no such thing as an unhandled exception on a thread pool thread. When a task throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then returns the thread to the thread pool.

– There is no such thing as an unhandled exception on a thread created with the Start method of the Thread class. When code running on such a thread throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then gracefully terminates the thread.

– There is no such thing as an unhandled exception on the finalizer thread. When a finalizer throws an exception that it does not handle, the runtime prints the exception stack trace to the console and then allows the finalizer thread to resume running finalizers.

The foreground or background status of a managed thread does not affect this behavior.

For unhandled exceptions on threads originating in unmanaged code, the difference is more subtle. The runtime JIT-attach dialog preempts the operating system dialog for managed exceptions or native exceptions on threads that have passed through native code. The process terminates in all cases.”

MSDN: “Exceptions in Managed Threads”

Page 43: MultiThreading in.NET 2.0 Neal S. Buchalter NSB Consulting NBuchalter@rcn.com

Neal S. Buchalter MultiThreading in .NET 2.0 May 6, 2006 Slide 43

References

Programming .NET Components, 2nd Edition, by Juval Löwy, © 2005, ISBN: 0-596-00762-0

MSDN Library:– Development Tools and Languages\Visual Studio\

C# Programming Guide\ Threading

– Development Tools and Languages\Visual Studio\.NET Framework Programming in Visual Studio\.NET Framework Advanced Development\ Threading

– Development Tools and Languages\Visual Studio\.NET Framework Programming in Visual Studio\.NET Framework Advanced Development\ MultithreadedProgramming with the Event-based Asynchronous Pattern