Sunteți pe pagina 1din 14

Threading in .

NET
Keeping apps responsive by Adrian Magdas

Agenda
why and when to use threads Asynchronous Programming Model (APM) vs Event-Based Asynchronous Pattern (EAP) ThreadPool class Timers TPL(Task Parallel Library .NET 4+) - quick coverage good/best practices

Agenda (cont.)
issues: deadlocks, race conditions, thread starvation, High CPU quick coverage of basic synchronization constructs Interlocked constructs queue based communication, optimization techniques recommended documentation

Why and when


Pros: - keep apps responsive by moving long running code on a different thread - robustness, if one thread blocks, the rest of the app/OS can still run - take advantage of the increasing number of cores or "The free lunch is over" - performance through parallelization (usually hard to achieve)

Why and when(cont.)


Cons: - memory footprint(~1MB/thread), on 32 bit machines, ~1600 threads before OOM - performance hit on context switch - madness: dozens of threads in an app which takes 0% CPU

Basics
Thread: wrapper over Windows native thread foreground vs background threads Thread pool: - worker threads for compute bound operations: ThreadPool. QueueUserWorkItem - IO bound from APM(file access, network, hardware) BackgroundWorker - don't use it as a timer or restart it a lot

Asynchronous Programming Model


compute bound or IO bound - compute bound uses ThreadPool - IO uses completion port + ThreadPool compute bound: BeginInvoke/EndInvoke IO bound: Stream, WebRequest, Socket, etc. - methods: BeginRead, EndRead, Begin/End - no thread involved, device capability: network, hdd - End_ uses ThreadPool for signaling completion

Task Parallel Library


build on top of APM nicer API adds support for cancellation and result retrieval adds optimization to ThreadPool queue to minimize synchronization, each Task has his own queue easy to handle in batches: WaitAny, WaitAll bad: only .NET 4 and up

Timers
System.Windows.Forms.Timer(EAP) - runs on UI thread, no synchronization needed System.Timers.Timer(EAP and ComponentModel) - do not use, wrapper over Threading.Timer System.Threading.Timer - this should be the default choice when a timer is needed

Issues when using threading


deadlocks: http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/10293249.aspx race conditions thread starvation High CPU - performance is affected complexity - see APM

Best practices
when using ThreadPool threads, don't block the thread, make all work atomic if possible always check for exceptions - in APM safely thrown on EndInvoke() - on manually created threads, if the exception is not caught inside the thread, an unhandled exception is thrown - KO design the application to minimize the number of locks required no locks inside for loops - KO

Best practices(cont.)
avoid too many context switches to UI thread, use a Timer to control the frequency and measure, 200-300ms should be fine avoid locking on the UI thread, modify the architecture if needed - see OrderBook V2 avoid locking on "this" or class name, narrow down the lock USE ThreadPool use SynchronizedQueue if you want to implement Thread Pool pattern: see OrderBook V2

References
CLR via C# - Jeffrey Richter PFX Team Microsoft http://blogs.msdn.com/b/pfxteam/ Joe Duffy http://www.bluebytesoftware.com/blog/Default.
aspx

Joseph Albahari http://www.albahari.com/threading/


http://herbsutter.com/welcome-to-the-jungle/ http://www.gotw.ca/publications/concurrency-ddj.htm

Code samples in Trader V2


APM
development\ultrader\ULCommonControls\Actions\TraderAction.cs

Queued Based communication and Timers:


development\ultrader\ULCommonControls\FlatModeDatasource\FlatOrderBook DataManager.cs

Synchronized Queue
development\ultrader\nOdisys\SynchronizedQueue.cs

S-ar putea să vă placă și