Example 8-1. Manual synchronization using fragmented locking

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Transactions; namespace WCFServiceProgramming.Library { [ServiceContract(SessionMode = SessionMode.Required)] public interface IMyContract { void MyMethod(); } [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] public class MyService : IMyContract { int[] _numbers; List<string> _names; [OperationBehavior(TransactionScopeRequired = true)] public void MyMethod() { lock (_numbers) { //... } // Don't access members here lock (_names) { //... } } } }
Example 8-2. Configure for reentrancy to allow callbacks

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Transactions; namespace WCFServiceProgramming.Library { [ServiceContract(CallbackContract = typeof(IMyContractCallback))] public interface IMyContract { [OperationContract] void MyMethod(); } public interface IMyContractCallback { [OperationContract] void OnCallback(); } [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)] public class MyService : IMyContract { public void MyMethod() { IMyContractCallback callback = OperationContext.Current.GetCallbackChannel<IMyContractCallback>(); callback.OnCallback(); } } }
Example 8-3. Using the service type as a shared lock

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Transactions; namespace WCFServiceProgramming.Library { [ServiceContract] public interface IMyContract { [OperationContract] void MyMethod(); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)] public class MyService : IMyContract { public void MyMethod() { lock (typeof(MyService)) { MyResource.DoWork(); } } } static class MyResource { public static void DoWork() { lock (typeof(MyService)) { } } } }
Example 8-4. Calling a resource on the correct synchronization context

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Transactions; using System.Threading; namespace WCFServiceProgramming.Library { [ServiceContract] public interface IMyContract { [OperationContract] void MyMethod(); } class MyResource { public SynchronizationContext MySynchronizationContext { get; } public int DoWork() { return 0; } } [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)] public class MyService : IMyContract { MyResource GetResource() { return new MyResource(); } public void MyMethod() { MyResource resource = GetResource(); SynchronizationContext context = resource.MySynchronizationContext; int result = 0; SendOrPostCallback doWork = delegate { result = resource.DoWork(); }; context.Send(doWork, null); } } }
Example 8-5. Encapsulating the synchronization context

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Transactions; using System.Threading; namespace WCFServiceProgramming.Library { [ServiceContract] public interface IMyContract { [OperationContract] void MyMethod(); } class MyResource { public int DoWork() { int result = 0; SendOrPostCallback doWork = delegate { result = DoWorkInternal(); }; MySynchronizationContext.Send(doWork, null); return result; } SynchronizationContext MySynchronizationContext { get; } int DoWorkInternal() { return 0; } } [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class MyService : IMyContract { MyResource GetResource() { return new MyResource(); } public void MyMethod() { MyResource resource = GetResource(); int result = resource.DoWork(); } } }
Example 8-6. Using the form synchronization context

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; using System.Diagnostics; using System.ServiceModel; namespace WCFServiceProgramming.Library { [ServiceContract] interface IFormManager { [OperationContract] void IncrementLabel(); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] class MyService : IFormManager { public void IncrementLabel() { MyForm form = Application.OpenForms[0] as MyForm; Debug.Assert(form != null); SendOrPostCallback callback = delegate { form.Counter++; }; form.MySynchronizationContext.Send(callback, null); } } partial class MyForm : Form { Label _counterLabel; SynchronizationContext _synchronizationContext; public MyForm() { //InitializeComponent(); _synchronizationContext = SynchronizationContext.Current; Debug.Assert(_synchronizationContext != null); } public SynchronizationContext MySynchronizationContext { get { return _synchronizationContext; } } public int Counter { get { return Convert.ToInt32(_counterLabel.Text); } set { _counterLabel.Text = value.ToString(); } } } }

using System; using System.Collections.Generic; using System.Linq; using System.Text; using WCFServiceProgramming.Library; using System.ServiceModel; namespace WCFServiceProgramming.Host { class Program { static void Main(string[] args) { ServiceHost host = new ServiceHost(typeof(MyService)); host.Open(); Application.Run(new MyForm()); host.Close(); } } }
Example 8-7. Encapsulating the synchronization context
Example 8-8. Using a safe control
Example 8-9. Hosting the service by the form
Example 8-10. Storing form reference in a thread-relative static variable
Example 8-11. Hosting on multiple UI threads
Example 8-12. Form as a singleton service
Example 8-13. Implementing FormHost<F>
Example 8-14. Installing AffinitySynchronizer
Example 8-15. Adding thread affinity support to ServiceHost<T>
Example 8-16. Implementing ThreadAffinityBehaviorAttribute
Example 8-17. Implementing ThreadAffinityHelper
Example 8-18. Manually synchronizing the callback with ConcurrencyMode.Single
Example 8-19. Manually synchronizing callback with ConcurrencyMode.Multiple
Example 8-20. Relying on the UI synchronization context for callbacks
Example 8-21. Explicitly opening a proxy to establish synchronization context
Example 8-22. Avoiding callback deadlock on the UI thread
Example 8-23. Setting custom synchronization context for the callback
Example 8-24. Applying the CallbackThreadAffinityBehavior attribute
Example 8-25. Implementing CallbackThreadAffinityBehaviorAttribute
Example 8-26. Asynchronous contract and proxy
Example 8-27. Simple asynchronous execution sequence
Example 8-28. UsingIasyncResult.AsyncWaitHandle to block until completion
Example 8-29. Using WaitOne( ) to specify wait timeout
Example 8-30. Waiting for completion of multiple methods
Example 8-31. Managing asynchronous call with a completion callback
Example 8-32. Passing an additional parameter using a state object
Example 8-33. Relying on completion callback synchronization context