Tuesday, July 24, 2012

Synchronization Context and Callbacks

SynchronizationContext 
The SynchronizationContext behavior is basically a configuration that allows the asynchronous and synchronization operations of the CLR to act appropriately while being used within various synchronization models. It also allows for a simple configuration of applications to work correctly under the different synchronization environments. This gives a service a quick way of associating itself with a particular synchronization context and then allowing WCF to detect that context and automatically marshal the call from the worker thread to the service synchronization context. The default value of UseSynchronizationContext is true. Affinity between the service, host and synchronization context is set when the host is opened. If the thread opening the host has a synchronization context and UseSynchronizationContext is true, WCF will establish an affinity between that synchronization context and all instances of the service hosted by that host. WCF will automatically marshal all incoming calls to the synchronization context. If UseSynchronizationContext is false, regardless of any synchronization context the opening thread might have, the service will have no affinity to any synchronization context. Interestingly enough, if UseSynchronizationContext is true but the opening thread has no synchronization context, the service will still not have one. By default, when executing the code below the client thread will be blocked while the return value is received from the service.

serviceProxy = new SomeService(new InstanceContext(this));
serviceProxy.Open();
MyObject = serviceProxy.CreateMyObject(new MyObject(1));

This is all fine on the surface. But, what would happen if the CreateMyObject function sends a callback? The client thread would be blocked. We can handle this with the callback behavior aspect of WCF. CallbackBehaviorAttribute.

UseSynchronizationContext
As a refresher, the CallbackContract property of a ServiceContract specifies the interface to define callback operations. This will create a dependent relationship between the interfaces. Once a CallbackContract is specified, the client will have to implement the callback functions in order to interact with the service at all. The CallbackBehavior setting for UseSynchronizationContext basically governs the affinity between the service and the client. You can easily override the automatic association of synchronization contexts with a simple decoration. By setting the UseSynchronizationContext property of the CallbackBehavior attribute to false, WCF will no longer guarantee a particular thread to be responsible for processing service requests. Instead, the operations will be automatically delegated to worker threads.

[CallbackBehavior(UseSynchronizationContext = false)]

When not using synchronization context on callback behavior, you may run into issues trying to directly update the UI, since those callbacks will no longer be on the UI thread.  One way around that would be to use a SendOrPostCallback delegate.

1 comment: