Click here to Skip to main content
13,248,927 members (41,436 online)
Click here to Skip to main content
Add your own
alternative version


31 bookmarked
Posted 12 Jan 2008

Context Delegate

, 12 Jan 2008
Rate this:
Please Sign up or sign in to vote.
This is an abstraction that facilitates (but is not limited to) building multi-threaded WinForms UIs.


What is ContextDelegate?

ContextDelegate is an abstraction that simplifies the delivery of callbacks into any event driven, single-threaded context. A context delegate can be described as a delegate with a built-in affinity to the “context” in which it is created. When such a delegate is invoked, the target method is invoked asynchronously in the original context in which the delegate was created. When the callback-recipient context is a UI context (e.g. WinForms, WebForms), the callback is dispatched on a UI thread within event boundaries. When the callback-recipient context has no special requirements, the callback is dispatched on any available thread (possibly the calling thread).

Why is ContextDelegate Needed?

Fundamentally, a client application is an event processing engine. Application code is typically comprised of visual and non-visual objects that collectively execute in an event driven single-threaded context. In more complex client applications, the roles of the visual and non-visual objects are formalized using a Model-View-Controller design pattern.

At any moment, only one event is being processed by the client application. Most Frameworks deliver system level asynchronous activity (e.g. key press, mouse click or move events) as simple events that are serially processed by the client application. No user interface object ever needs to allow for the possibility of multiple system events racing with each other on multiple threads.

With the advent of multi-threaded client applications, it becomes necessary for the application to deal with non-system asynchronous events (e.g. arrival of data from a server, completion of a long calculation). Historically, it has been left to the application developer to arrange for these events to be safely processed by the same context (i.e. thread) that processes system events. Most resulting ad-hoc solutions involved writing a complex and error-prone mix of thread-safe and single-threaded logic. This in turn, ultimately destroyed the original simplicity and predictability of the event-driven, single-threaded UI model.

ContextDelegate provides a transparent way to deliver any application generated asynchronous event with the same contract as system level events. This allows these events to be handled with the same simplicity as system level events (e.g. keyboard clicks).

What is a Practical Example?

A typical pattern for publish/subscribe client applications involves a set of one or more threads that subscribe to published updates from a publisher and invoke callbacks for processing of those updates. The callbacks must be executed on the client (i.e. UI) thread. The callbacks must be delivered in a manner that maintains responsiveness of the user interface, even when the frequency of updates is high. ContextDelegate handles the necessary plumbing to make this possible with a minimum of effort by the application developer.

ContextDelegate Usage

While there are several types involved in the facility, only the ContextDelegate class is used by the client. The multithreaded service is unaware that it is dealing with a context-sensitive callback. A typical usage idiom involves the following events.

  1. The client code creates a “regular” .NET delegate.
  2. The client code calls the static ContextDelegate.Create() method to create a context-sensitive delegate from the regular .NET delegate that is passed as the only parameter. A Delegate type is returned from the Create() method. The returned delegate refers to the original delegate and implies a strong reference to the target object.
  3. The client code “passes” the returned “context-sensitive” delegate returned from the Create() method to a multithreaded service.
  4. The multithreaded service invokes the “context-sensitive” delegate.
  5. The context-sensitive delegate invokes the original delegate in the context specified by the callback creator.

If the target method for the delegate is decorated with the [ThreadNeutral] attribute, the ContextDelegate.Create() method does not perform any special marshalling. This makes it possible for the ContextDelegate facility to transparently support context-sensitive and context-insensitive observers.

ContextDelegate Implementation

There are classes, interfaces, structs, and attributes involved in the ContextDelegate facility.

Name Type Purpose
AtomicCount struct Multithread-safe counter used by the callback scheduler to maintain statistics about the number of pending callbacks for a specific context.
Context class The Context for a callback consists of a scheduler, a queue of pending callbacks, and a map of delegate facades.
ContextDelegate class The public class used by the client code to create a context-sensitive delegate.
DelegateFactory class Default Factory which recreates a .NET delegate with no facade.
Facade class Provides a facade for a .NET delegate that supports context-sensitive dispatch.
Factory class Used to recreate context delegates. Advanced functionality not used by typical application code.
IDelegateFactory interface Interface used to recreate a context delegate from the underlying method and target object. Advanced functionality not used by typical application code.
IDelegateProxy interface Interface used to access the underlying method or target object. Advanced functionality not used by typical application code.
IScheduler interface The interface implemented by context-sensitive delegate schedulers.
MessageWnd class A non-display window used to schedule callbacks by the STAScheduler.
STAScheduler class A scheduler for standard apartment model threads (i.e. WinForms client code). This scheduler ensures that callbacks are delivered in a manner that ensures user interface responsiveness.
WebScheduler class A scheduler for ASP.NET client applications.
ThreadNeutral attribute Methods with this attribute will have context-sensitive delegates invoked on any available thread including the calling thread.
User32 class Singleton class that exposes selected Win32 API calls used in message dispatch.
WeakMap class A map that maintains only weak references to keys and values. WeakMap is used by the Context class to hold facades.

The ContextDelegate facility currently supports .NET delegates with the following parameter signatures:

  • (object sender, EventArgs args)
  • (IAsyncResult result)
  • (object returnValue)
  • ()

The Facade class can be extended to support other signatures. The facility currently supports a scheduler for WinForms and ASP.NET applications.

The classes in the ContextDelegate facility interact in the following manner.


1Creates a Context with an associated scheduler and dispatch queue.
2Calls the CreateDelegate method of Context to create a Facade for the requested delegate signature.


3Creates a Facade for the requested delegate signature.
5Queues pending callbacks for the associated scheduler. Calls the Schedule method of the associated scheduler to schedule the dispatch of the callback.


4Calls the Post method of Context to schedule a callback.


6Calls the Post method of the MessageWnd to post a WM_USER message.
7Supplies the message procedure to handle the message posted to the MessageWnd. This message procedure is called in the context (i.e. thread) of the client that created the scheduler.
8Calls the Dispatch method of Context to actually invoke the callback.


Visual Studio 2005 projects for the ContextDelegate implementation and a sample WinForms client application are provided in ZIP file attachments. Use the CtxDelegateSample.sln to build and execute ContextDelegate and the sample.

The ContextDelegate implementation runs in production with high update rate multithreaded services. Nevertheless, there are some aspects of the implementation that can be enhanced or further generalized. These are appropriately marked in the source code.

The sample application displays updates from a background subscriber thread on a listbox. The background thread is unaware that it is calling a method that requires UI context. The delegate used by the background thread is passed, along with update rate and update count. The callback from the thread procedure is marshaled to the UI thread by ContextDelegate. The updates are displayed in the UI thread and the user interface remains completely responsive even with high update rates.

Future Articles

In future articles, more advanced usage of ContextDelegate by infrastructure services will be explored. An ASP.NET sample application will be provided. Solutions for high update rate environments (e.g. real-time market data), within an MVC pattern, will be described.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralBackgroundWorker Pin
Alomgir Miah Abdul22-Jan-09 6:48
memberAlomgir Miah Abdul22-Jan-09 6:48 
GeneralRe: BackgroundWorker Pin
Kalkunte24-Jan-09 6:01
memberKalkunte24-Jan-09 6:01 
GeneralGood work Pin
Radim Tylecek31-Jul-08 1:30
memberRadim Tylecek31-Jul-08 1:30 
GeneralRe: Good work Pin
Kalkunte31-Jul-08 10:12
memberKalkunte31-Jul-08 10:12 
GeneralRe: Good work Pin
Radim Tylecek31-Jul-08 21:30
memberRadim Tylecek31-Jul-08 21:30 
GeneralRe: Good work Pin
Kalkunte2-Aug-08 10:09
memberKalkunte2-Aug-08 10:09 
Sounds great! Cool | :cool:

Thanks for the keywords.

As for the Dispatcher, it is really centered around WPF event dispatch. The facility I created was intended to abstract away the general concept of marshaling callbacks into an arbitrary UI context, not just Winforms or WPF UIs. I use ContextDelegates for both WinForms and ASP .Net/AJAX applications, and I intend to elaborate on the concept if necessary to support WPF.

More than likely, I'll change the implementation of the ContextDelegate scheduler for WinForms to delegate to the .Net 3.0 Dispatcher class. This would fit in with the new dispatch model, while preserving the simpler usage pattern of ContextDelegates.
GeneralWIN32 usage is deprecated Pin
_elli_12-Jan-08 7:16
member_elli_12-Jan-08 7:16 
GeneralRe: WIN32 usage is deprecated [modified] Pin
User of Users Group12-Jan-08 10:32
memberUser of Users Group12-Jan-08 10:32 
GeneralRe: WIN32 usage is deprecated Pin
Kalkunte13-Jan-08 22:17
memberKalkunte13-Jan-08 22:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.171114.1 | Last Updated 12 Jan 2008
Article Copyright 2008 by Kalkunte
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid