Threading, Synchronizing, And Performing Asynchronous Operations In the 'NET Framework

1 / 52
About This Presentation
Title:

Threading, Synchronizing, And Performing Asynchronous Operations In the 'NET Framework

Description:

Threading, Synchronizing, And Performing Asynchronous Operations In the .NET Framework ... can actually degrade performance if used incorrectly ... –

Number of Views:169
Avg rating:3.0/5.0
Slides: 53
Provided by: downloadM
Category:

less

Transcript and Presenter's Notes

Title: Threading, Synchronizing, And Performing Asynchronous Operations In the 'NET Framework


1
Threading, Synchronizing, And Performing
Asynchronous Operations In the .NET Framework
  • Hans Verbeeck
  • Developer Consultant
  • Microsoft EMEA

2
Objectives
  • Asynchronous execution
  • Managing threads
  • Synchronization techniques

3
Threads
  • A thread is an entity that allows your code to
    run
  • allocated face time with the CPU
  • has a stack and a private storage area for
    variables
  • confined to a process space
  • Each program begins execution with a primary
    thread
  • begins execution at application entry point (e.g.
    Sub Main)
  • shares CPU time with other threads executing on
    same machine
  • can spawn secondary threads within its process

process
Module MyApp ' application entry point '
runs on primary thread Sub Main() ' your
code End Sub End Module
Thread
4
Each process has one or more threads
5
UI threads
  • Primary thread in Windows application is a UI
    thread
  • UI thread listens to internal message loop for
    event notifications
  • UI thread executes form and control event handler
  • UI thread in charge of keeping application
    responsive to user
  • Windows Forms are inherently single-threaded

Public Class Form1 Inherits Form Sub
Handler(.. .) Handles cmdExecuteTask.Click
' perform work End Sub End Class
process
UI Thread
6
The System.Threading.Thread class
  • CLR wraps each OS thread with instance of the
    Thread class
  • allows applications to query and control threads
  • reference to current thread acquired using
    CurrentThread property
  • Helpful methods for writing code to test
    threading
  • Thread.Sleep pauses current thread for specified
    time
  • AppDomain.GetCurrentThreadId returns ID of Win32
    thread
  • System.Diagnostics (Process and ProcessThread
    classes)

Imports System.Threading Module MyApp Sub
Main() ' get reference to current thread
object Dim MyCurrentThread As Thread
Thread.CurrentThread Dim b As Boolean
MyCurrentThread.IsBackground ' put this
thread to sleep for 5 seconds
Thread.Sleep(5000) ' get Win32 thread ID
of current thread Dim ID As Integer ID
AppDomain.CurrentDomain.GetCurrentThreadId()
End Sub End Module
Win32 Thread
Thread class instance
7
DEMO I have a question
8
Windows applications and long-running tasks
  • Executing long-running tasks on UI thread freezes
    application
  • application cannot respond to events until task
    has completed

Public Class Form1 Inherits Form Sub
cmdExecuteTask_Click(ByVal sender As Object, _
ByVal e As EventArgs) _
Handles
cmdExecuteTask.Click ' execute
long-running task Task1(10) End Sub Sub
Task1(ByVal loops As Integer) Dim i As
Integer, message As String For i 1 To
loops ' perform some extended work
Threading.Thread.CurrentThread.Sleep(1000)
' Update UI about status of task message
"Task is " (i / loops).ToString("0.00") "
complete" lblUpdateStatus.Text message
lblUpdateStatus.Update() Next End
Sub End Class
9
DEMO The incredibly hanging app
10
Motivation for asynchronous execution
  • Windows applications may require asynchronous
    execution
  • Application can execute task asynchronously on
    worker thread
  • worker thread can run long-running tasks without
    blocking UI
  • useful for tasks like printing, file I/O,
    cross-network calls, etc.

process
UI Thread
WorkerThread
Sub Task1( ) ' perform work End Sub
11
Hazards of asynchronous execution(or how an OS
is like a frietkot)
  • Asynchronous execution is not always the right
    choice
  • task switching required to share processor is not
    free
  • can actually degrade performance if used
    incorrectly
  • must take explicit steps to protect shared data
  • adds to program complexity
  • successful test run does not equal program
    correctness
  • timing related issues difficult to uncover or
    reproduce
  • debugging is more difficult
  • not all libraries are prepared for concurrent
    access
  • Invest time early evaluating the payoff before
    multithreading!
  • Remember VB.NET components ARE NOT thread safe
    by default!
  • Unlike VB 6 where you code was inherently
    protected by the single-threading apartment

12
Asynchronous execution
  • There are four techniques to execute a method
    asynchronously
  • calling BeginInvoke on a delegate
  • using the Threading.ThreadPool class
  • using the Threading.Timer class
  • creating a new instance of the Threading.Thread
    class
  • First three techniques leverage thread pool
    supplied by CLR
  • makes it fairly easy to run methods asynchronously

process
CLR thread pool
UI Thread
Workerthread
Workerthread
Workerthread
13
Delegates defined
  • Delegates represent a major abstraction in the
    CLR
  • added to programming model to formalize callback
    pattern
  • a delegate is bound to one or more method
    implementations
  • caller uses delegate to indirectly execute bound
    methods
  • Delegates provide important functionality to .NET
    Framework
  • delegates provide foundation for multicasting of
    notifications
  • delegates provide primary means for asynchronous
    execution
  • delegates provide foundation for CLR events

14
Asynchronous execution using a delegate
  • Delegates facilitate asynchronous method
    execution
  • BeginInvoke does not block calling thread
  • BeginInvoke enqueues request for asynchronous
    execution
  • asynchronous execution handled by pool of worker
    threads

Delegate Sub TaskRunnerDelegate(ByVal loop As
Integer) Module MyApp Sub Main() '
create delegate Dim del As TaskRunnerDelegate
del AddressOf Tasks.Task1 ' execute
delegate asynchronously del.BeginInvoke(10,
Nothing, Nothing) End Sub End Module Module
Tasks Sub Task1(ByVal loops As Integer)
' implementation End Sub End Module
UI Thread
Workerthread
15
IAsyncResult
  • BeginInvoke returns an IAsyncResult object
  • object used to manage asynchronous call in
    progress
  • object can be used to poll for completion

Module MyApp Sub Main() ' create
delegate Dim del As TaskRunnerDelegate
AddressOf Tasks.Task1 ' execute delegate
asynchronously Dim ar As IAsyncResult
del.BeginInvoke(10, Nothing, Nothing) Do
Until ar.IsCompleted ' do something
while waiting Loop ' task on secondary
has now completed End Sub End Module
16
EndInvoke
  • If work is not completed then EndInvoke blocks
    calling thread until delegate completes call
  • object can be used to harvest output parameters
    and return value
  • object can be used to check whether call
    experienced exceptions

Delegate Function Delegate1(ByVal x As Integer,
ByRef y As Double) As String Module Tasks
Function Method1(ByVal x As Integer, ByRef y As
Double) As String ' implementation End
Function End Module Module MyApp Sub Main()
Dim del As Delegate1 AddressOf Tasks.Method1
Dim param1 As Integer 10, param2 As Double,
retval As String ' (1) queue up task to
run on worker thread from CLR thread pool Dim
ar As IAsyncResult del.BeginInvoke(param1,
param2, Nothing, Nothing) ' (2) do
something interesting on UI thread ' (3)
attempt to harvest output parameter and return
value Try Dim retval as String
del.EndInvoke(param2, ar) Catch ex As
Exception ' handle cases where
asynchronous task experienced exception End
Try End Sub End Module
17
Asynchronous execution using callback object
  • You can register callback object for notification
    of completion
  • callback method must be based on AsyncCallback
    delegate
  • callback delegate passed as parameter to
    BeginInvoke
  • callback method run on thread from CLR thread pool

Module MyApp Sub Main() ' create
delegate for asynchronous request Dim del As
TaskRunnerDelegate AddressOf Tasks.Task1
' create delegate callback object Dim cb
As New AsyncCallback(AddressOf MyCallbackMethod1)
' execute delegate asynchronously and
setup callback Dim ar As IAsyncResult
del.BeginInvoke(10, cb, del) End Sub '
method signature conforms to AsyncCallback
delegate Sub MyCallbackMethod1(ByVal ar As
IAsyncResult) Dim del As TaskRunnerDelegate
del CType(ar.AsyncState, TaskRunnerDelegate)
Dim s As String del.EndInvoke(ar) End
Sub End Module
18
Raising events asynchronously
  • How do you raise an event asynchronously?
  • cannot be done using RaiseEvent keyword
  • call GetInvocationList and execute BeginIvoke on
    each target
  • synchronizing completion of all notifications far
    more tedious

Delegate Sub MyBroadcastDelegate() Class
EventSource1 Event Event1 As
MyBroadcastDelegate ? Sub NotifyAllListers()
' enumerate through each target Dim
target As MyBroadcastDelegate For Each target
In Event1Event.GetInvocationList ' call
BeginInvoke to queue up asynch notification
target.BeginInvoke(Nothing, Nothing) Next
End Sub End Class
19
Threading constraints of Windows Forms
  • Each form and control is managed by a specific UI
    thread
  • you should never access forms or controls with
    any other thread
  • callback objects should not update controls
    directly
  • Control class provides methods for
    thread-switching
  • Invoke executes method synchronously on control's
    thread
  • BeginInvoke executes method asynchronously on
    control's thread
  • Form and control classes inherit these methods
    from Control class
  • Invoke, BeginInvoke, EndInvoke and CreateGraphics
    are safe, all the other methods...arent

20
Imports System.Threading Public Class Form1
Inherits Form Delegate Sub TaskRunnerDelegate(B
yVal loops As Integer) Delegate Sub
StatusUpdateDelegate(ByVal StatusMessage As
String) Private Sub cmdExecuteTask_Click( )
Handles cmdExecuteTask.Click Dim del As
TaskRunnerDelegate AddressOf Task1 Dim cb
As New AsyncCallback(AddressOf MyCallbackMethod1)
Dim ar As IAsyncResult del.BeginInvoke(10,
cb, del) End Sub ' task run on worker
thread from CLR thread pool Function
Task1(ByVal loops As Integer) As String '
implementation of long-running task End
Function ' callback method also run on
worker thread from CLR thread pool Sub
MyCallbackMethod1(ByVal ar As IAsyncResult)
Dim UiDelegate As New StatusUpdateDelegate(Address
Of UpdateStatus) Dim args() As String
"Task is complete" Me.Invoke(UiDelegate,
args) End Sub ' code to update form or
controls run on primary UI thread Sub
UpdateStatus(ByVal StatusMessage As String)
lblUpdateStatus.Text StatusMessage
lblUpdateStatus.Update() End Sub End Class
21
DEMO A piece of pi
22
Using the CLR thread pool directly
  • You can directly register callback with the CLR
    thread pool
  • Create delegate instance based on WaitCallback
    delegate
  • Call ThreadPool.QueueUserWorkItem
  • Tasks are queued for execution on thread from CLR
    thread pool

Imports System.Threading Module MyApp Sub
Main() ' queue up task to run on
secondary thread Dim cb As New
WaitCallback(AddressOf Tasks.MyAsyncProc)
ThreadPool.QueueUserWorkItem(cb, Nothing) End
Sub End Module Module Tasks Sub
MyAsyncProc(ByVal objState As Object) ' do
work on thread from CLR thread pool End Sub End
Module
23
DEMO A pool of fractals
24
Timers
  • System.Windows.Forms.Timer
  • implemented using window messages (WM_TIMER)
  • timer callback fires only on form thread
  • not very precise only fires when message
    queue idle
  • System.Threading.Timer
  • thread pool-based implementation
  • callback always occurs on thread-pool thread
  • can be scheduled for arbitrary start date/time
  • System.Timers.Timer
  • thread pool-based implementation
  • configurable support for callback only on form
    thread
  • supports use in forms designer

25
Using System.Threading.Timer
Imports System.Threading Module MyApp1 Sub
Main() ' setup timer callback to fire
once in 3 seconds Dim cb As New
TimerCallback(AddressOf Tasks.MyTimerProc)
Dim tmr As New Timer(cb, Nothing, 3000, 0) End
Sub End Module Module Tasks Sub
MyTimerProc(ByVal objState As Object) ' do
work on thread 2 on timer callback End Sub End
Module
26
Using System.Timers.Timer
Imports System.Timers Module Module1 Sub
Main() ' Fire at 1 second intervals (starting 1
second from now). Dim tmr As New
Timer(1000) AddHandler tmr.Elapsed, AddressOf
Tasks.OnTimerFired tmr.Start() ' Do
some work on thread 1 End Sub End
Module Module Tasks Sub OnTimerFired(ByVal
sender As Object, ByVal e As ElapsedEventArgs) Di
m tmr As Timer CType(sender, Timer) ' do work
on thread 2 on timer callback End Sub End
Module
27
DEMO Its time for a demo
28
Using dedicated threads
  • Although preferred for the general case,
    thread-pooling techniques are not suited to all
    problems
  • performing very lengthy/blocking operations
  • prioritizing multiple tasks relative to each
    other
  • controlling COM apartment affiliation (interop
    scenarios only)
  • want threads existence to hold process running
  • System.Threading.Thread supports the creation and
    scheduling of dedicated threads
  • programmer controls thread creation
  • programmer controls thread priority
  • programmer can suspend/resume thread arbitrarily
  • programmer controls apartment affiliation
  • programmer controls thread name (aids in
    debugging)

29
Creating threads with the Thread class
  • Threads can be spawned by calling New on Thread
    class
  • constructor requires delegate for parameter-less
    Sub procedure
  • call to Thread.Start creates new Win32 OS-level
    thread
  • call Thread.Join to suspend current thread until
    other thread ends
  • technique does not use the CLR thread pool

Imports System.Threading Module MyApp Sub
Main() Dim t As New Thread(AddressOf
Tasks.MyAsynchTask) t.Start() ' start
secondary task on thread 2 '??? ' do
work in parallel on thread 1 t.Join() '
now wait for thread 2 to end End Sub End
Module Module Tasks Sub MyAsynchTask()
' do work on thread 2 End Sub End Module
30
Controlling an executing thread
  • Manipulate thread execution with methods on
    thread object
  • Abort raises unrecoverable ThreadAbortException
    in thread
  • Interrupt raises recoverable ThreadInterruptExcept
    ion in thread
  • Sleep pauses the thread for a fixed time
  • Suspend pauses thread indefinitely
  • Resume resumes execution in a paused thread
  • Some aspects of thread control are limited to
    safepoints
  • Some requests may not be enforced immediately

Sub ManipulateThread(t As Thread)
t.Sleep(3000) ' pause thread for 3 seconds
t.Suspend() ' pause thread indefinitely
t.Resume() ' resume execution of paused thread
t.Interrupt() ' raise a trappable error in
thread t.Abort() 'doom thread by raising
unrecoverable error End Sub
31
DEMO Working with System.Threading.Thread
We dont encourage it so no demo
32
CLR philosophy on threading
  • CLR encourages programmers to avoid creating
    threads
  • not required to achieve asynchronous behavior
  • not required to achieve parallel execution
  • asynchronous delegates are often a much better
    choice
  • Spawning threads explicitly has disadvantages
  • requires more work to create and manage threads
  • requires more work to join together parallel
    tasks
  • ignores thread pool provided by the CLR

33
Comparing asynchronous execution alternatives
  • Differences are in terms of scalability and
    context
  • scalable to large work loads?
  • CAS markers on initiating thread stack
    propagated?
  • security principal of initiating thread
    propagated?
  • call context of initiating thread propagated?

34
CAS Markers
static void baz() static void bar(int x)
(new SomePermission()).Deny() baz() static
void Main() bar(5)
...baz locals... 00000000 SD for baz 00000000
preserved esi 0006ee8c preserved ebp 02d42dc2
bar return address 00000000 (eval
stack)/junk 00000000 SD for bar 00000000
preserved esi 0006eea4 preserved ebp 02d42d4b
Main return address 00000005 arg x 00000000 SD
for main 00000000 preserved esi 0006eec4
preserved ebp
...baz locals... 00000000 SD for baz 00000000
preserved esi 0006ee8c preserved ebp 02d42dc2
bar return address 00000000 (eval
stack)/junk 00b70e60 SD for bar 00000000
preserved esi 0006eea4 preserved ebp 02d42d4b
Main return address 00000005 arg x 00000000 SD
for main 00000000 preserved esi 0006eec4
preserved ebp
FrameSecurityDescriptor
m_assertions
m_denials
m_restrictions
SomePermission
35
Synchronization
  • An application with multiple threads needs
    additional attention
  • system may switch threads at inopportune times
  • two threads may go after same data at same time
  • data must be locked (synchronized) to avoid this
  • CLR provides multiple synchronization techniques
  • SyncBlock in object header can be used to lock an
    object
  • manually synchronization techniques also
    available
  • If no synchronization is applied, default is no
    synchronization
  • leads to unexpected and unpredictable results
  • often a poor choice for multithreaded applications

36
By default, VB.NET classes are not thread-safe
  • Code run in multithreaded environments requires
    extra attention
  • classes and objects must be robust in the face of
    concurrency

' this is an example of a class that is not
thread-safe Class Point Private x As Integer
Private y As Integer Sub New(ByVal x As
Integer, ByVal y As Integer) Me.x x
Me.y y End Sub ' method to update point
position Sub SetPointPosition(ByVal x As
Integer, ByVal y As Integer) Me.x x
Me.y y End Sub ' method to read point
position Sub GetPointPosition(ByRef x As
Integer, ByRef y As Integer) x Me.x y
Me.y End Sub End Class
37
Inconsistent states and concurrency
  • Code running on one thread can leave data in
    inconsistent state
  • code running on other threads is vulnerable to
    inconsistent reads
  • programmers must provide synchronization through
    locking

Module MyApp Sub Main() Dim pt As New
Point(10, 10) pt.SetPointPosition(20, 20)
End Sub End Module
Thread
Point
start consistent state
Sub SetPointPosition( ) ' data consistent
at start Me.x x ' data inconsistent in
middle Me.y y ' data consistent at
end End Sub
Point
middle inconsistent state
Point
end consistent state
38
Monitors
  • CLR provides built-in lock for each reference
    type instance
  • an object's lock is accessible through Monitor
    class
  • resources for lock allocated upon first use

Thread 2
Thread 1
Point
39
Monitors and locking
Thread
  • Monitor class has methods for locking
  • Enter method acquires (or waits for) lock
  • Exit method release lock

Point
Time 1 consistent state
Time 2 acquire lock
Point
Time 3 inconsistent state
Sub SetPointPosition( ... ) ' acquire lock
using Monitor Monitor.Enter(Me) '
perform thread safe operations Me.x x Me.y
y ' release lock using Monitor
Monitor.Exit(Me) End Sub
Point
Time 4 consistent state
Time 5 release lock
40
A thread-safe class
' this is an example of a thread-safe
class Class Point ' private fields
Private x As Integer Private y As Integer
' update point position Sub
SetPointPosition(ByVal x As Integer, ByVal y As
Integer) Monitor.Enter(Me) Me.x x
Me.y y Monitor.Exit(Me) End Sub '
read point position Sub GetPointPosition(ByRef
x As Integer, ByRef y As Integer)
Monitor.Enter(Me) x Me.x y Me.y
Monitor.Exit(Me) End Sub End Class
41
SyncLock
  • VB.NET provides the SyncLock statement for
    convenience
  • SyncLock adds code to acquire lock by entering
    monitor
  • SyncLock structures code into Try statement
  • SyncLock adds code to call Monitor.Exit in
    Finally block

Sub SetPointPosition( ... ) ' you type this
code SyncLock Me Me.x x Me.y y
End SyncLock End Sub
Sub SetPointPosition( ... ) ' VB.NET
produces code like this Monitor.Enter(Me)
Try Me.x x Me.y y Finally
Monitor.Exit(Me) End Try End Sub
42
Locking granularity
  • Any object can serve as a locking mechanism
  • instances of Object class can be created for
    additional locks

Class TwoPoints Private x1, y1 As Integer
Private lock1 As New Object() Private x2, y2 As
Integer Private lock2 As New Object() '
update point1 position Sub SetPoint1Position(ByV
al x As Integer, ByVal y As Integer) SyncLock
lock1 Me.x1 x Me.y1 y End
SyncLock End Sub ' read point1 position
Sub GetPoint1Position(ByRef x As Integer, ByRef y
As Integer) SyncLock lock1 x Me.x1
y Me.y1 End SyncLock End Sub '
methods for accessing point2 omitted for
clarity End Class
43
ReaderWriterLock
  • ReaderWriterLock allows for concurrency with
    multiple readers
  • can perform better than exclusive locking
    (monitor and SyncLock)

Class Point Private x, y As Integer Private
lock As New ReaderWriterLock() ' update
point position Sub SetPointPosition(ByVal x As
Integer, ByVal y As Integer)
lock.AcquireWriterLock(5000) Try Me.x
x Me.y y Finally lock.ReleaseWriterL
ock() End Try End Sub ' read point
position Sub GetPointPosition(ByRef x As
Integer, ByRef y As Integer)
lock.AcquireReaderLock(5000) Try x
Me.x y Me.y Finally
lock.ReleaseReaderLock() End Try End
Sub End Class
44
Waiting and Pulsing a monitor
  • Monitors can block a thread
  • Wait method of Monitor blocks current thread
    indefinitely
  • Wait method releases the lock after blocking
    thread
  • Can accrue multiple threads
  • Monitors can sequentially release threads
  • Pulse method of Monitor releases one blocked
    thread
  • Thread pulsing is FIFO
  • PulseAll method releases all threads sequentially

45
Using Pulse and Wait methods with a Monitor
Class RequestList Private Shared InnerList As
New Queue() Shared Function GetNextRequest()
As String Threading.Monitor.Enter(InnerList)
If InnerList.Count 0 Then
Threading.Monitor.Wait(InnerList) End If
Threading.Monitor.Exit(InnerList) Return
InnerList.Dequeue() End Function Shared Sub
PostRequest(ByVal req As String)
Threading.Monitor.Enter(InnerList)
InnerList.Enqueue(req) Threading.Monitor.Pulse
(InnerList) Threading.Monitor.Exit(InnerList)
End Sub End Class
46
Synchronizing Methods
  • Methods can be synchronized as a unit
  • MethodImpl attribute in System.Runtime.CompilerSer
    vices
  • Set attribute value to MethodImplOptions.Synchroni
    zed
  • Only one thread enters method at a time
  • Can be applied to methods and constructors
  • Not applicable to fields or properties
  • Can use with both shared and instance
    methods/constructors
  • Does not involve objects SyncBlock

ltMethodImpl(MethodImplOptions.Synchronized)gt
_ Public Shared Sub Foo() MsgBox("only one
call to Foo executes at a time") End Sub
47
More Manual Synchronization Options
  • Interlocked class
  • Lives in System.Threading namespace
  • Used for atomic operations on variables
  • AutoResetEvent
  • Blocks one thread until another thread sets an
    event
  • ManualResetEvent
  • Notifies waiting threads of some event
  • Mutex
  • Mutual exclusion manual blocking mechanism
  • MethodImplAttribute
  • Similar to a critical section
  • A method attribute defined in the
    System.Runtime.CompilerServices namespace

48
An Alternative use COM
  • Use System.EnterpriseServices to do the work for
    you
  • Inherit from ServicedComponent
  • Enabled Synchronization, other features
  • Configure application to run as a library
    application
  • Advantages
  • Microsoft does the dirty work (like STAs)
  • You still get to live in the MTA however (unlike
    STAs)
  • Disadvantages
  • Will not work on Windows 98, 98SE, or ME
  • Prefer Windows 2000 or higher
  • Requires Admin privileges for first run if using
    XCOPY deployment with auto-install

49
COM Interop Compatibility
  • By default, .NET threads are COM unaware
  • The first call you make via interop requires the
    runtime to call CoInitialize on the thread to
    setup the COM apartment
  • If you are going to be calling VB 6-based COM
    components (or other STA based components, you
    should decorate you main entry point with the
    STAThread attribute
  • If using ASP.NET you want to set the ASPCompat
    attribute to true.

50
Nice to know...
  • Threading is not supported on all clients in the
    same way. (Im talking about WIN98 here).
  • There is a Threading Tutorial in the MSDN help.
  • Some cool tools available for free
    fromhttp//www.sysinternals.com

51
Summary
  • Multithreading brings increased capability and
    responsibility
  • Can request threads from existing pool or create
    new threads
  • Thread synchronization controls data access
  • Can synchronize with Context or SyncBlock

52
(No Transcript)
Write a Comment
User Comments (0)
About PowerShow.com