xviii
C# 4.0: The Complete Reference
Formatting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715
Formatting Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 715
The Numeric Format Specifi ers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 716
Understanding Argument Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . 718
Using String.Format( ) and ToString( ) to Format Data . . . . . . . . . . . . . . . . . 719
Using String.Format( ) to Format Values . . . . . . . . . . . . . . . . . . . . . . . 719
Using ToString( ) to Format Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 721
Creating a Custom Numeric Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 722
The Custom Format Placeholder Characters . . . . . . . . . . . . . . . . . . . . 722
Formatting Date and Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 726
Creating a Custom Date and Time Format . . . . . . . . . . . . . . . . . . . . . . 728
Formatting Time Spans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 730
Formatting Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 732
23 Multithreaded Programming, Part One . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 735
Multithreading Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 736
The Thread Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 737
Creating and Starting a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 737
Some Simple Improvements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 739
Creating Multiple Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 740
Determining When a Thread Ends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 742
Passing an Argument to a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 745
The IsBackground Property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 747
Thread Priorities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 747
Synchronization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 750
An Alternative Approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 754
The Monitor Class and lock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 755
Thread Communication Using Wait( ), Pulse( ), and PulseAll( ) . . . . . . . . . 756
An Example That Uses Wait( ) and Pulse( ) . . . . . . . . . . . . . . . . . . . . . 756
Deadlock and Race Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 760
Using MethodImplAttribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 760
Using a Mutex and a Semaphore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 762
The Mutex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 762
The Semaphore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 766
Using Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 769
The Interlocked Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 772
Synchronization Classes Added by .NET 4.0 . . . . . . . . . . . . . . . . . . . . . . . . . . 773
Terminating a Thread Via Abort( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 774
An Abort( ) Alternative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 775
Canceling Abort( ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777
Suspending and Resuming a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 778
Determining a Thread’s State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 779
Using the Main Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 779
Additional Multithreading Features Added by .NET 4.0 . . . . . . . . . . . . . . . . 780
Multithreading Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 781
Starting a Separate Task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 781