wcfasynchronousinteropwcf-interoperability

WCF - Are Asynchronous Services interoperable?


Basically as the question states, if I make my services asynchronous does that mean they aren't interoperable anymore?


Solution

  • As far as the client is concerned, a sync or an async version of the service are identical (see example below). So the sync/async decision does not affect interoperability.

    public class StackOverflow_6231864_751090
    {
        [ServiceContract(Name = "ITest")]
        public interface ITest
        {
            [OperationContract]
            string Echo(string text);
            [OperationContract]
            int Add(int x, int y);
        }
        [ServiceContract(Name = "ITest")]
        public interface ITestAsync
        {
            [OperationContract(AsyncPattern = true)]
            IAsyncResult BeginEcho(string text, AsyncCallback callback, object state);
            string EndEcho(IAsyncResult ar);
            [OperationContract(AsyncPattern = true)]
            IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state);
            int EndAdd(IAsyncResult ar);
        }
        public class Service : ITest
        {
            public string Echo(string text) { return text; }
            public int Add(int x, int y) { return x + y; }
        }
        public class ServiceAsync : ITestAsync
        {
            string Echo(string text) { return text; }
            int Add(int x, int y) { return x + y; }
            public IAsyncResult BeginEcho(string text, AsyncCallback callback, object state)
            {
                Func<string, string> func = Echo;
                return func.BeginInvoke(text, callback, state);
            }
    
            public string EndEcho(IAsyncResult ar)
            {
                Func<string, string> func = (Func<string, string>)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate;
                return func.EndInvoke(ar);
            }
    
            public IAsyncResult BeginAdd(int x, int y, AsyncCallback callback, object state)
            {
                Func<int, int, int> func = Add;
                return func.BeginInvoke(x, y, callback, state);
            }
    
            public int EndAdd(IAsyncResult ar)
            {
                Func<int, int, int> func = (Func<int, int, int>)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate;
                return func.EndInvoke(ar);
            }
        }
        public static void Test()
        {
            foreach (bool useAsync in new bool[] { false, true })
            {
                Type contractType = useAsync ? typeof(ITestAsync) : typeof(ITest);
                Type serviceType = useAsync ? typeof(ServiceAsync) : typeof(Service);
                Console.WriteLine("Using {0} service implementation", useAsync ? "Asynchronous" : "Synchronous");
                string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
                ServiceHost host = new ServiceHost(serviceType, new Uri(baseAddress));
                host.AddServiceEndpoint(contractType, new BasicHttpBinding(), "");
                host.Open();
                Console.WriteLine("Host opened");
    
                Console.WriteLine("Using the same client for both services...");
                ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
                ITest proxy = factory.CreateChannel();
                Console.WriteLine(proxy.Echo("Hello"));
                Console.WriteLine(proxy.Add(3, 4));
    
                ((IClientChannel)proxy).Close();
                factory.Close();
    
                host.Close();
    
                Console.WriteLine("Done");
                Console.WriteLine();
            }
        }
    }