Monday, August 19, 2013

The .NET Asynchrony And Multithreading lecture (in progress, not finished)

Plain Threading
    Thread.Sleep(0) vs Thread.Yield()
    Foreground and Background Threads
    finally blocks in the execution stack of background threads are circumvented
        (including using)
    Thread Priority
    Memory-mapped files
    Exception Handling
        Swallow of an exception in the main thread.
        Centralized exception handling
            global event
            only for an UI thread
            AppDomain.CurrentDomain.UnhandledException
                app will shutdown or <legacyunhandledexceptionpolicy>

Thread Pooling
    Thread.CurrentThread.IsThreadPoolThread
    Oversubscription
        hill-climbing algorithm
    Optimizing the Thread Pool
    How Does the Minimum Thread Count Work?

States
    Synchronous
        Thread-Local Storage - "TLS"
            ThreadLocal<t> Class
            ThreadStaticAttribute
        Lazy<t> Class
    Asyncronous
        ExecutionContext - "EC"
            built by AsyncTaskMethodBuilder
            flowing EC
                var ec = ExecutionContext.Capture();
                ExecutionContext.Run(ec, delegate...
                All async API do this implicitly
            Stored in a Task object
            EC is cache for the SecurityContext, HostExecutionContext, CallContext etc.
        SynchronizationContext - "SC"
            built by the support for awaiting Task and Task<tresult>
            SynchronizationContext.Current.Post(delegate
            Main classes
                WindowsFormSynchronizationContext
                DispatcherSynchronizationContext
                SynchronizationContext (default; for the ThreadPool)
                AspNetSynchronizationContext
            The Schedulers in the Reactive Extensions is a more featured analog for SC.
            + ASP.NET subtle
            aspnet:UseTaskFriendlySynchronizationContext
            Presence of SC (capture of it) overrides default marshaling of a continuation delegate to the TreadPool
                Presence of SC is disabled by the ConfigureAwait (false)
                It calls "Avoiding excessive bouncing" optimization
        SynchronizationContext vs ExecutionContext
            a jump (marshaling) for SC vs a ambient for EC
            SC is supressed by ConfigureAwait (false).
                ConfigureAwait(false) on every await of a task is usefull for library implementers
            EC is supressed ExecutionContext.SuppressFlow
            EC can hold SC
                There's quite a mess with it.
                API design's mistake to hold the SC in the EC
                Difference with the internal and public EC.Capture and EC.Run
                    The problem: a second async method will be executed on a Dispatcher
                    It cause a drawback for performance.
                    In short, SynchronizationContext.Current does not “flow” across C#'s "await" key word points.
                    But flows exists in public custom implementations.

Threading (blocking)
    Raw & Old
    Blocking
        Simple blocking methods
            Sleep(), someThread.Join, Task.Wait, EndInvoke
        Blocking Versus Spinning
    Locking constructs
        Exclusive locking (Locking)
            Monitor (lock)
                lockTaken, TryEnter
                Locking and Atomicity
                Nested Locking
                Deadlocks
                    OOP uncountable with the Parallel Programming
                    Dispatcher.Invoke
            Mutex
                50 times slower than a lock
                prefix its name with Global

        Nonexclusive locking
            Semaphore
                thread-agnostic
            SemaphoreSlim
            ReaderWriterLockSlim
            Spinning
                SpinLock and SpinWait
                while (!proceed) Thread.Sleep (10);
    Signaling constructs
        Event Wait Handles
            EventWaitHandle
                AutoResetEvent
                ManualResetEvent
            ManualResetEventSlim
            CountdownEvent
        Monitor’s Wait/Pulse methods
        ThreadPool.RegisterWaitForSingleObject
        Barrier classes
        WaitHandle
            Set, WaitOne, and Reset
            WaitAny, WaitAll, and SignalAndWait
            Alternatives to WaitAll and SignalAndWait
        Signaling with Wait and Puls by Monitor
            Wait and Pulse pattern
            Producer/Consumer Queue vs BlockingCollection<t>
    Nonblocking synchronization constructs
        Thread.MemoryBarrier()
        Thread.VolatileRead, Thread.VolatileWrite
        volatile keyword
        VolatileRead and VolatileWrite approach
        Interlocked class
    Thread Safety approaches
        Singleton with exclusive lock for access
        Stateless approach
        To subclass ContextBoundObject and apply the Synchronization attribute to the class
        Static methods
        Read-only thread safety
        Activation model for stateless apps
        Thread Affinity (Dispatcher, SC)
            Invoke works synchronously
        Immutable Objects

Challenges
    Race Condition
    I/O-bound versus compute-bound
        I/O-bound operations
            An operation that spends most of its time waiting for something to happen
            an example is downloading a web page or calling Console.ReadLine
            involve input or output
            Thread.Sleep is also deemed I/O-bound
            Delayed by I/O operations
        compute-bound operations
            an operation that spends most of its time performing CPU-intensive work
            Delayed by intensive calculations
            have a big processor's time consumption
    course-grained vs fine-grained concurrency
        course-grained concurrency
            a single concurrent operation that spans many methods
            BackgroundWorker as an example.
        fine-grained concurrency
            a sequence of small concurrent operations, in between which execution bounces to the UI thread.
            excessively fine-grained asynchrony can hurt performance
                by overhead

Obsolete Patterns
    ## Asynchronous Programming Model (APM)
        Begin (with AsyncCallback), End prefixed methods + IAsyncResult
        Task.Factory.FromAsync
    Asynchronous delegates
        It's the APM pattern
        It has huge overhead
        the Task replaces it completely
            with Run and ContinueWith
    ## Event-Based Asynchronous Pattern (EAP)
        Encapsulation of a asynchrony logic in a single object
        with the exposing of a *Completed suffixes event.
    BackgroundWorker
        It's the general-purpose EAP implementation.
        Created for rich-client apps.

Tasks
    It's the main state-container for the asynchrony now in the .NET.
    Manual threads approach lack
    Wait
    Multi long-running tasks
        TaskCreationOptions.LongRunning
        Others...
    Exceptions
        Convenient propagation
        autonomous tasks
        TaskScheduler.UnobservedTaskException
    Continuations
        GetResult
        ConfigureAwait
        ContinueWith
        TaskContinuationOptions
    TaskCompletionSource
    Task.Delay

await and async
    "await"
        may be only inside "async" method.
        Except: catch, finally, lock, unsafe context,
            or an executable’s entry point (main method)
        Captures context
    All "async" methods returns the Task or Task<tresult>.
        Except: Void-returning async methods have a specific purpose:
            to make asynchronous event handlers possible.
            Have lack with
                erorr-handling.
                    An exception will be raised directly on the SynchronizationContext.
                    The catch block will be ignored.
                        See AppDomain.UnhandledException or similar for UI.
                            that is "recipe for unmaintainability"
                Completion
                    can't be composed by using the await
                    useless for Task.WhenAny, Task.WhenAll and so on.
                    A workaround is a custom SC.
                difficult for a testing
    async methods may be static.
    Asynchronous Lambda Expressions
        unnamed async methods
    async+return+compiler+task
    event handlers
        myButton.Click += async (sender, args) =>
    WinRT - IAsyncInfo
        IAsyncAction, IAsyncOperation<tresult>
        AsTask, await
    Asynchrony and Synchronization Contexts (SynchronizationContexts)
        global exception posting with synchronization context
            void vs a Task return
            throw before await
            same like the yield
            ASP.NET - OperationStarted, OperationCompleted
    Optimizations
        Completing synchronously
            Implicit return by compiler by TaskCompletionSource
            someTask.GetAwaiter() -> awaiter.IsCompleted
            small overhead for awaiting
            Task.FromResult, returns an already-signaled task vs async without awaiting
            Don't mark method async if it returns a Task from other async method
        Avoiding excessive bouncing
            ConfigureAwait (false);
                synchronization context ignoring in a deep sync call stack
                (especially for a loop with async call in it)

Asynchronous Patterns
    Cancellation
        OperationCanceledException - predefined exception
        CancellationTokenSource + CancellationToken - pattern implementation
        WinRT follow an inferior protocol (pattern)
        CancellationToken.Register - cancellation callback + disposing
        IsCanceled vs IsFaulted
    Progress Reporting
        IProgress<t> and Progress<t>
        synchronization context
        WinRT IAsyncInfo...
            .AsTask (cancelToken, progress);
    The Task-based Asynchronous Pattern (TAP)
        summary
    Task Combinators
        await Task.WhenAny(...)
            await await - exceptions are then re-thrown without an AggregateException wrapping.
            await task; - Unwrap result/re-throw
            WhenAny with differently typed tasks gives untemplayed (untyped) task.
        await Task.WhenAll(...)
            Exception.InnerExceptions.Count
            Task<tresult>
            uris.Select (async uri => (await new WebClient().DownloadDataTaskAsync (uri)).Length);
        Custom combinations + encapsulation
            ContinueWith is more convenient than GetAwaiter().OnCompleted
    Cache like approach (see above: Optimizations, Completing synchronously)
        If a value cached async method returns synchronosly.
            Task.FromResult<tresult>(result) for the Task<t> or Task.FromResult<object>(null) for Task.
            Before .NET 4.5:
                var source = new TaskCompletionSource<result>();
                source.SetResult(theResult);
                return source.Task;
    Avoiding excessive bouncing (see above)
Tackle with the Async and the Threading when combined
    Async (async await) <> Threading (blocks the current thread)
        await <> Task.Wait, Task.Result, someThread.Join... (Wait backgrond operation or its result)
        await Task.Delay <> Thread.Sleep (Wait a period of time)
        await Task.Yield <> Thread.Yield
        await Task.WhenAny <> Task.WaitAny, WaitHandle.WaitAny (Wait for any operation to complete)
        await Task.WhenAll <> Task.WaitAll, WaitHandle.WaitAll (Retrieve the results of multiple tasks)
    Task.Factory.StartNew is dangerous (too raw)
    Deadlocks
        var delayTask = DelayAsync();
        delayTask.Wait();
        Try to use the Context-free code (SC free)
            await AsyncMethod().ConfigureAwait(continueOnCapturedContext: false);
    Avoiding excessive bouncing (see above)


TPL Dataflow or Reactive Extensions

Literature

No comments:

Post a Comment