WCF - Асинхронные службы совместимы? - PullRequest
1 голос
/ 03 июня 2011

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

Ответы [ 3 ]

2 голосов
/ 04 июня 2011

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

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();
        }
    }
}
1 голос
/ 04 июня 2011

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

Вот хороший ресурс: Как: асинхронно вызывать операции службы 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! :)
    }
}
1 голос
/ 04 июня 2011

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

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

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

и

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

...