Title: Events, Delegates and Callbacks
1Events, Delegates and Callbacks
2introduction
- two C keywords
- delegate
- event
- a common concept
- callback
- read Williams, pp 159 -179
3what is an event-driven application?
- a program that (after initializing itself and
registering for some events) executes code only
in response to an event (callback) - what is a GUI doing when no event is occurring?
- sometimes people say its monitoring the message
loop - they might also say its waiting for a message
to be sent by an event - its not asleep, but its also not doing much of
anything - and where do events originate?
- Observable classes (such as controls)
- any class can decide to expose (publish) an
observable event - events are not confined to user interface
controls!
4events and controls
- in a Windows application, a form hosts the
controls placed on it - the form subscribes handler methods to the
controls events - the form only subscribes to the events that it
needs - the control calls back the handler when the
event occurs - some events raised by controls are very common
- for example, many control classes define a Click
event - if a user clicks the control, the control object
detects the click and notifies its subscribers by
means of the Click event - the subscribed Form method may be said to be the
Click handler - some events are raised in conjunction with other
events - e.g., a DoubleClick event also involves
- MouseDown, MouseUp, and Click
5code that defines a delegate
- public delegate void WhatEver (string
message)
- a delegate is a special class
- defined by a single line of code, outside of
other classes - a delegate carries a reference to a method
- the delegate enforces the signature of the
method it carries - delegate instances are created using the new
keyword - a method name is always sent to the
constructor - WhatEver myDel new WhatEver(myMethod)
6when am I likely to need a delegate ?
- anytime a method is passed as a parameter
- references to methods are always passed inside
delegate objects - a delegate is needed to start a separate thread
- every method to be passed as a parameter must
have a signature that conforms to a corresponding
delegate class - type safety
- one-to-many notifications (events)
- observer classes subscribe (using ) to events
- this adds a delegate to the notification list
kept by the event - cross-thread communications, including
- explicit thread creation
- remote calls to DLLs
- any situation that uses callbacks
7delegate code is tricky
- public delegate int WhichEver (string
message, int number)
- syntax differs in VB.NET and C.NET
- speech about delegates tends to be ambiguous
- may not distinguish definition vs. instantiation
(using new) - they say create a delegate in either case
- you cannot recognize a delegate by its name!
- you can recognize a delegate by its context, or
location, within code
8defining vs. instantiating
- public delegate void WhatEver (string
message)
- in a class having a method of the correct
signature - void myMethod(string somestring)
-
-
- WhatEver myDel new WhatEver(myMethod)
9a delegate is needed to start a thread
- code to be executed by a new thread
- private void DoSomething()
-
- // code for new thread goes here
-
- to create a new thread
- Thread myNewThread new Thread (new ThreadStart
(this.DoSomething) ) - myNewThread.Start()
- ThreadStart is defined somewhere in the
System.Threading library
10a very common use of delegates
- implementing the Observer pattern
- see the Design Patterns book (Gang of Four 1995),
pp 293-303 - a one-to-many dependency between objects
- when one object changes state, all its dependents
are notified automatically - a subject keeps a list of observers
- the subject notifies all observers when anything
changes - each observer conforms to an abstract interface
known to the subject - observers must subscribe to the subject to
receive the notifications - the Gang of Four did not invent the idea
- commonly also described as a subscriber paradigm
- its needed all over the place
- Observer - Observable in Java
11traditional implementation of the Observer pattern
- two interfaces
- IObserver
- ISubject
- objects implementing IObserver register with the
subject - an object implementing ISubject must
- manage a list of registered observers
- notify all registered observers when a state
change occurs - usually by calling a Notify() method declared in
the IObserver interface - a subject might pass data to the observer as part
of Notify() - OR
- observers might need to call a method in the
ISubject interface to obtain more information
about the state change
12C supports the Observer pattern with the event
keyword
- but first, a word of warning...
13many imprecise definitions exist for event
- heres a very common one
- An event is an action which you can respond to,
or handle, in code. - heres another
- Events can be generated by a user action, such
as clicking the mouse or pressing a key, by
program code, or by the system. - these definitions are for the unwashed masses
- they will not help you understand the event
keyword in C - dont end up like this guy because you failed to
learn what an event really is
14will the real definition please stand up?
- event is a keyword in C
- an event is a special object created in the
Observable class - it automatically manages a list of subscribers
- less code is needed to register, unregister and
notify observers - this is the area where most coding errors used to
occur! - no IObserver and ISubject interfaces are needed
15the Window designer registers event handlers for
you
- void mnuExit_Click (object o, EventArgs e)
-
- // do something about the click here
-
- mnuExit.Click new System.EventHandler
(this.mnuExit_Click) - an event is an object defined inside an
Observable class - such as the controls offered in the Windows
designer toolbar - for example, a menu control will define many
possible events - show in VS.NET where the events can be viewed
- each event manages a list of subscribers for the
Observable class
16Observers subscribe to an event
- observers register to receive notifications from
raised events - Button button1 new Button() // create an
Observable object - button1.Click new System.EventHandler
(button1Click) - void button1Click (object o, EventArgs e)
-
- // do something about the click here
-
- EventHandler defined in the System library
- public delegate void EventHandler (object o,
EventArgs e) - an EventArgs class is also defined in the System
library
17observer vs. observable
- observers register to receive notifications about
events, as in this form - Button button1 new Button() // create an
Observable object - button1.Click new System.EventHandler
(button1Click) - void button1Click (object o, EventArgs e)
-
- // do something about the click here
-
- observables (subjects, publishers) define and
raise an event - public event EventHandler Click // define
an event called Click - if (Click ! null) Click ( this, new
EventArgs() )
18event arguments
- delegates for event handlers should always pass
two arguments from the event to the handler - a reference to the sender (type object)
- 2) a reference to an EventArgs object (or an
extension of it) - private void btnExit_Click (object sender,
System.EventArgs e) -
- // event handled here
-
- the event passes both arguments to all
subscribers - the observers callback function (event handler)
may seek more information about what triggered
the event - via methods or properties of the EventArgs object
19Its the lawfor every event, there must first
be a delegate
- a delegate must be defined before an event can be
defined - observers may register an appropriate callback
method with the event - to register means to send a delegate to the
event - the Observable class calls (raises) the event
when its state changes, - the event then runs through the list of collected
delegates, calling in turn the method referenced
by each delegate - what if nobody registers for an event?
- the event then has an emply list
- this is why you must always check whether an
event is null before raising it (calling it) in
the Observable class
20show FormDismissal demo code
21raising an event in C
- Observer (Subscriber) launches a form and
registers for the forms dismiss event - public Form myForm new Form()
- myForm.FormDismissed new EventHandler(
this.HandleDismissal ) - myForm.Show()
- private void HandleDismissal (object sender,
EventArgs e) -
- this.textBox1.Text The
FormDismissed event was raised. -
-
- --------------------------------------------------
--------------------------------------------------
------------------------------------- - Observable (Publisher) code defines an event and
raises it when it gets dismissed - public event EventHandler FormDismissed
22customizing event arguments
- public delegate void StringEventHandler
(object o, StringEventArgs e) - public class StringEventArgs
System.EventArgs -
- private readonly string myMessage
- public StringEventArgs (string
theMessage) // overload the constructor -
- myMessage theMessage
-
- public string Message
-
- get return myMessage
- set
-
23raising an event in C with a customized argument
- Observer (Subscriber) launches a form and
registers for the forms dismiss event - public frmGetString myForm new frmGetString()
- myForm.FormDismissed new StringEventHandler(
this.ItHappened ) - myForm.Show()
- private void ItHappened (object sender,
StringEventArgs e) -
- this.textBox1.Text e.Message
-
-
- --------------------------------------------------
--------------------------------------------------
------------------------------------- - Observable (Publisher) code defines an event and
raises it when it gets dismissed - public event StringEventHandler FormDismissed
24subscribing and unsubscribing
- given the following delegate class declaration
-
- public delegate void EventHandler (object o,
EventArgs e) - and the following event definition in a Button
component - public event EventHandler Click
- to subscribe (in a Form)
- myButton.Click new EventHandler(myButton_Click)
- to unsubscribe (in a Form)
- myButton.Click - new EventHandler(myButton_Click)
25how events manage subscribers
- new subscribers are added to the end of the list
- when an event is raised, subscribers are called
in turn, from beginning to end - if a method is on the list multiple times, it
gets invoked multiple times - removing a subscribed method removes the last
method of that name from the list
26warning!
- events are references
- they can be null
- youll get an exception if your Observable calls
a null event - so, do it like this
- if (ThisEvent!null) ThisEvent(this, new
EventArgs()) // raise events only if non-null
27Corners game example
- extending a Windows control
- using events to create a Model-View-Controller
design
28what is a callback?
- a situation where a method gets passed around as
an argument - event-handling methods can also be referred to as
callback methods - but an event is not required just to call back
- a delegate can be passed to another class, which
can then call the delegates method back - any time you want another class to call this
method, you have to send the other class a
delegate that contains the method - this is called registering even if no event is
involved - show Delegate Example code here
29possible callback scenarios
- when a thread creates another thread
- the new thread can call back to tell the
original thread something - asynchronous calls (perhaps across a network)
- iIf you dont want your thread to block while
waiting for a response - make the call asynchronously
- sometime later, you get a callback from the
caller - the caller executes the handler method whose
reference you sent it - even if the callee is in-process, it might take
too long to wait for - maybe you just want another class to be able to
call your method - you enable a callback situation by exposing the
method to the other class - registering with the other class
- this just involves send a delegate to the other
class - the other class must have a public method you can
call to send the delegate - or you might send the delegate as an argument to
the other class constructor - show my blog prototype here?
30invoking delegates asynchronously
- usually, we can call the method inside a
delegate using the Invoke() method of the
delegate - but, so the caller wont block until the called
method completes, we can use instead - BeginInvoke() / EndInvoke()
- BeginInvoke(args, null, null)
- people call this fire and forget
- BeginInvoke returns an IAsyncResult object
- you can then call its IsCompleted() method to
check status - EndInvoke() can harvest a return value
31Remoting
- a Remote Procedure Calls (RPC) requires a
delegate - RPC types must be either Serializable or extend
MarshallByRefObject - RPC types must correspond to value and reference
semantics for the remote object - that is, you have to know exactly how to call the
remote thing
32Remoting
- uses channels and formatters
- a channel is communications protocol
- TcpChannel, HttpChannel
- a formatter determines what the type looks like
on the channel - SoapFormatter, BinaryFormatter
- you can customize things by extending
- IChannel, Iformatter
- it helps just to look at somebodys working code
33code with a formatter
- private void serialize()
-
- try
-
- fs new FileStream(settings_files
pec, FileMode.Create) - formatter new SoapFormatter()
- formatter.Serialize(fs, hashtbl)
-
- catch (Exception e)
-
- throw new Exception("StoredSetting
s.serialize " e.Message,e) -
- finally
-
- if (fs!null) fs.Close() fs
null - if (formatter!null) formatter
null -
-
34delegates and their role
- observer and observable in Java
- sender (observable) and listener (observing)
- server (observable) and client (observing)
- delegates are classes commonly used within the
.NET Framework to build event-handling mechanisms - delegates roughly equate to function pointers in
C and C - delegates are object-oriented, type-safe, and
secure - .NET provides an event model that uses
delegates - is somewhat different, and perhaps more flexible,
than Javas Observer-Observable paradigm
35delegates are needed in several very different
scenarios
- three separate sets of functionality have been
dumped into the single keyword 'delegate - the ability to pass a method like an object, e.g.
as a parameter to another method - the easy ability to allow many subscribers for a
single event publisher - asynchronous callbacks, with BeginInvoke/EndInvoke
- any delegate you create automatically has all
these capabilities - in practice, you generally only use one of the
three aspects at a time - this could be a questionable design decision
- it makes it more difficult to come up to speed
with delegates and events - but, they are very powerful!
36we can now do some interesting things!
- we saw before that an event provides a
one-to-many notification... - delegates also allow multiple events to be bound
to the one method, allowing a many-to-one
notification - for example, a button-click event and a
menu-commandclick event can both invoke the same
delegate... - ...which then calls a single method to handle
these separate events the same way - you can also just forward the event to another
event - possibly easier and more straightforward
- delegates permit very late runtime binding to
methods - a delegate can be bound at run time to any
method whose signature matches its class
declaration - this just means you can create a delegate object
anytime and send it to another class, which can
then call you back - this feature allows you to set up or change the
methods youre going to use based on runtime
conditions which could not be foreseen at compile
time - for example, you could use this to choose a
communications protocol at runtime (rather than
compiling with a fixed protocol in your code) - or, you could dynamically attach an event handler
to a control to change the controls behavior on
the fly - delegates help us implement the asyncronous
calling pattern (fire and forget)
37the end of this PowerPoint file
Hooray!