.NET threading in C# Training Highlights sharing

Jeffery’s training: .NET Threading in C#: Building Responsive, Reliable & Scalable Code

I’d like to share some highlights with you. And the demo code is here: www.wintellect.com/2397

1. Introduction

  • Early OS had just 1 thread, and then Windows supports multiple threads for robustness instead of performance.
    • n Bad products use lots of threads but most of the time doing nothing (low CPU usage). For example: Movie Maker, Outlook and Visual Studio
  • Threads are overhead
    • Kernel objects in CPU registers: x86=~700bytes, x64=~1240bytes,IA64=~2500bytes
    • User-mode stack: 1MB committed
    • Kernel-mode stack:12KB/24KB
    • For parameter/local var, exception-handling chain: …
    • Dll attach/detach notifications: hundreds of functions are called
  • Window pre-empts running thread and schedules another (non-waiting) thread each quantum (~20ms), which is called a context switch. Every context switch requires that Windows
    • Enter kernel mode (very expensive)
    • Save registers from CPU to running thread’s kernel object (x86=~700bytes, x64=~1240bytes,IA64=~2500bytes)
    • Determine which thread to schedule next. If thread owned by other process, switch address space (very expensive)
    • Load register from selected thread’s kernel object into CPU
    • Leave kernel mode.
  • Conclusion
    • avoid threads: they are time/memory overhead
    • use threads: they enable robustness & scalability on multi-CPU system
  • Using thread
    • Framework class library has 2 namespaces for process/thread
    • Discourage: System.Diagnostics(Process & ProcessThread), providing Windows’view
    • Encourage: System.Threading(Thread), providing CLR managed view
  • Constructing one thread doesn't have Windows create a thread. Instead, Start() does.
  • Sleep(Timespan timeout) suspends a thread at least timeout timespan.
    • Every thread has a base priority number, 0(lowest & reversed) to 31(highest), Windows boosts a thread’s priority when an event occurs.
    • Windows Thread vs CLR Thread
      • Thread’s ManagedThreadId in CLR differs from ProcessThread’s Id in Windows
      • Some properties are only in Windows, such as ProcessorAffinity, useful to assign task to a specific processor.
      • Some properties are only in CLR, such as IsBackground(true if thread won’t force app to stay alive)
    • Threading support in VS
      • Thread window
      • You can select which thread to step through
      • You can freeze/thaw threads to take them out of the picture

2. Performing Asynchronous Operations with the CLR’s Thread Pool

  • There is one ThreadPool per process, shared by all AppDomains.
  • If work items queue quickly, more threads are created; If work items reduce, a ThreadPool thread waits 2 minutes, wake and kills itself.
  • Thread pools should never have a max thread limit
  • There are mainly 2 kinds of task need thread
    • Compute-Bound
      • When to create your own thread instead of using threadpool
        • Non-normal thread priority
        • Foreground thread to keep app alive until work item is done
        • Long-running compute-bound task
        • Aborting the operation
      • Periodically performing asynchronous compute-bound operation: System.Threading.Timer. 2 more timers:
        • System.Windows.Forms.Timer: all work is done by just 1 thread
        • System.Timers.Timer: System.Threading.Timer ‘s wrapper to support VS design time operation.
    • I/O-Bound

3. The CLR’s Asynchronous Programming Model

  • CLR creates 1 IOCP per process and creates thread pool threads that wait on the IOCP.
  • Standard pattern to execute asynchronous operations
    • I/O-bound: BeginXXX for many classes, such as Stream, Dns, Socket, WebRequest, SqlCommand
    • Computer-bound: BeginInvoke
  • If you don't’ specify the FileOptions.Asynchronous flag, Windows performs synchronous operations, which is very inefficient.
  • Windows always performs some File I/O operations synchronously: Compression, Extending a file’s length by appending, Cached data.
  • APM supports 3 rendezvous techniques
    • Wait until done: BeginXXX and then EndXXX
    • Polling: BeginXXX, and then call IAsyncResult.IsCompleted repeatedly, and then EndXXX
    • Callback: 
      • I/O-bound: BeginXXX, ThreadPool thread calls device, ThreadPool thread back to ThreadPool, … callback, EndXXX
      • Compute-bound: BeginInvoke, ThreadPool thread works, EndInvoke
  • Exception 
    • BeginXXX throw exception: no item queued
    • Operation fails: EndXXX will throw exception
  • APM Usage Note
    • Must call EndXXX or you will leak resources.
    • Just call EndXXX once or result is unpredictable.
    • Call EndXXX with the same object used by BeginXXX or you will get InvalidOperationException
    • Many Win32 API don’t offer async versions
  • WinForm and WPF GUI only can be updated in thread who creates the windows. This is not APM
  • WebForm can be configured as async rendering in ASP.NET 2.0: Async=”true” as page directive in aspx file and some BeginXXX, EndXXX methods.

4. The Event-Based Asynchronous Programming Model

5. Thread Synchronization

  • Thread safety
    • All static Framework Class library are thread safe
    • Framework Class library Instance methods are usually not thread safe.
    • .NET Fx v1.x collections had confusing thread-safe wrappers, which have been removed in .NET Fx 2.0 (ArrayList.Synchronized(new ArrayList());) 
  •  Code optimization by c#/JIT complier and CPU reordering may execute your code out of program order.
    • VolatileRead/VilotileWrite/memory barrier(memory fence)
    • Avoid using volatile keyword
  • Manipulate an Int32 in a thread-safe way: Interlock
  • Monitor, lock
    • Double-check locking technique
  • ReaderWriterLock
  • Window Kernel Objects 
    • System.Threading.WaitHandle (Mutex,Semaphore, EventWaitHandle(AutoResetEvent/ManualResetEvent))
    • ThreadPool offers an efficiend way to execute a method when a kernel object becomes signaled:ThreadPool.RegisterWaitForSingleObject
  • Conclusion
    • Always do async I/O, because sync I/O blocks a thread.
    • Avoid using a thread for a dedicated task, because it blocks unless task runs at 100% CPU utilization continuously.
    • Avoid using thread synchronization constructs, because they can block a thread.
    • Use volatile Reads/Writes & Interlocked methods, because they are extremely fast, never block a thread.

6. The Art of Thread Synchronization. Referring to his book and free power threading library

7. Aborting a Thread

你可能感兴趣的:(reading)