WCF - Асинхронные службы совместимы?

По сути, как гласит вопрос, если я сделаю свои сервисы асинхронными, значит ли это, что они больше не взаимодействуют?

3 ответа

Решение

Что касается клиента, то синхронизация или асинхронная версия службы идентичны (см. Пример ниже). Таким образом, решение о синхронизации / асинхронности не влияет на совместимость.

public class Stackru_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();
        }
    }
}

Ваши службы не должны делать что-то "особенное" ... они по-прежнему ведут себя так же. С другой стороны, ваши клиенты должны использовать сервисы, используя асинхронный шаблон. Самый простой способ сделать это, если вы используете "Добавить ссылку на службу...". Просто установите флажок "Генерировать асинхронные операции" и вуаля, вы можете делать асинхронные вызовы для вашей службы...

Вот хороший ресурс: Как: Асинхронно вызывать операции службы WCF

Несмотря на негативные комментарии, пример в конце хорошо поставлен. Просто подпишитесь на событие Completed, а затем сделайте асинхронный вызов. Вызов сделан, ваш поток пользовательского интерфейса освобождается, и как только вызов завершается, событие вызывается! Будьте осторожны с вашими новыми найденными способностями!

public class Foo
{
    private BarServiceClient client;

    public Foo()
    {
        client = new BarServiceClient();
        client.DoWorkCompleted += Client_DoWorkCompleted;
    }

    private void Client_DoWorkCompleted(object sender, DoWorkCompletedEventArgs e)
    {
        //e.Result contains your result.
    }

    public void DoBar()
    {
        client.DoWorkAsync(); //Called asynchronously, UI thread is free! :)
    }
}

Если "сделать сервис асинхронным", вы имеете в виду использование AsyncPatternтогда я понимаю, что это никак не влияет на клиента, только на то, как среда выполнения WCF вызывает ваши операции на сервере. Клиент (то есть клиент WCF), как всегда, сам выбирает, использовать ли асинхронные вызовы.

С этой страницы MSDN:

Чтобы определить контрактную операцию X, которая выполняется асинхронно, независимо от того, как она вызывается в клиентском приложении...

а также:

В этом случае асинхронная операция отображается в метаданных в той же форме, что и синхронная операция: она представляет собой одну операцию с сообщением запроса и коррелированным ответным сообщением. У клиентских моделей программирования есть выбор. Они могут представлять этот шаблон как синхронную операцию или как асинхронную, при условии, что когда служба вызывается, происходит обмен сообщениями запрос-ответ.

Другие вопросы по тегам