Async CTP - Как я могу использовать async / await для вызова службы wcf? - PullRequest
15 голосов
/ 04 ноября 2010

Если бы я вызвал метод службы WCF, я бы сделал что-то вроде этого:

proxy.DoSomethingAsync();
proxy.DoSomethingAsyncCompleted += OnDoSomethingAsyncCompleted;

Как я мог бы сделать то же самое, используя новый async ctp?Я думаю, мне нужно что-то вроде proxy.DoSomethingTaskAsync или proxy.DoSomethingAsync().ToTask()?Вызов веб-службы должен возвращать Task<T>, чтобы можно было использовать ключевое слово await, но как ??

Ответы [ 6 ]

10 голосов
/ 04 ноября 2010

В CTP есть фабричные методы, которые превращают обычные функции APM (Begin / End) в те, которые совместимы с новым ключевым словом async, например:

Stream s = new FileStream("C:\test.txt", FileMode.CreateNew);
byte []buffer = new byte[100];
int numBytesRead = await Task<int>.Factory.FromAsync(s.BeginRead, s.EndRead, buffer, 0, buffer.Length, null);

Так что в вашем случае вы можете сделать эквивалент, а затем вы бы назвали его так:

async proxy.DoSomethingTaskAsync()

См. в этой теме в группе обсуждения CTP для получения дополнительной информации

6 голосов
/ 05 апреля 2012

Асинхронный сервис, использующий async-await, очень отзывчив, поскольку он может чередовать многие клиентские вызовы и выполнять их параллельно (2).Несмотря на это, служба может быть полностью поточно-ориентированной в одном потоке (3) и может быть одноэтапной службой (1) или объектом службы, созданным средой для сеанса или только для вызова.

При реализацииОбратите внимание, что ServiceBehaviourAttributes (1) ... (3):

    [ServiceContract( Namespace="X", Name="TheContract" )]
    public interface IAsyncContractForClientAndService
    {
        [OperationContract]
        Task<TResponse> SendReceiveAsync( TRequest req );
    }



    [ServiceBehavior (InstanceContextMode = InstanceContextMode.Single, // (1)
                      // also works with InstanceContextMode.PerSession or PerCall
                      ConcurrencyMode     = ConcurrencyMode.Multiple,   // (2)
                      UseSynchronizationContext = true)]                // (3)

    public MyService : IAsyncContractForClientAndService
    {
        public async Task<TResponse> SendReceiveAsync( TRequest req )
        {
            DoSomethingSynchronous();
            await SomethingAsynchronous(); 
            // await lets other clients call the service here or at any await in
            // subfunctions. Calls from clients execute 'interleaved'.
            return new TResponse( ... );
        }
    }

Для выполнения каждого вызова в одном потоке System.Threading.SynchronizationContext.Current! = null должен присутствовать вВ тот момент, когда вы открываете () ServiceHost.Используя SynchronizationContext, вам не нужно заботиться о блокировках.Атомарные, не прерываемые фрагменты кода растягиваются примерно от одного ожидания к другому.Позаботьтесь о том, чтобы данные общего сервиса находились в согласованном состоянии при каждом ожидании, и имейте в виду, что последовательные запросы от одного клиента могут отвечать не в том порядке, в котором они были отправлены.

На стороне клиента асинхронная операция сервиса является ожидаемой:

   var response = await client.Channel.SendReceiveAsync( request );

Невозможно использовать параметры out или ref в договоре на эксплуатацию.Все данные ответа должны передаваться возвращаемым значением Task (T).
Я использую этот интерфейс в AsyncWcfLib , он поддерживает Модель программирования на основе актера .

4 голосов
/ 13 ноября 2010

В Async CTP есть образец WCF, который покажет вам, как использовать модель async / await в WCF.

Что касается планов поддержки этой модели в WCF, вы можете взглянуть на следующий пост:

http://blogs.msdn.com/b/endpoint/archive/2010/11/13/simplified-asynchronous-programming-model-in-wcf-with-async-await.aspx

Надеюсь, это поможет.

Амадео

2 голосов
/ 22 марта 2012

Довольно часто асинхронные клиенты вызывают синхронный сервис.
Следующие контракты между клиентом и сервисом совпадают (немного закулисной магии):

    [ServiceContract( Namespace="X", Name="TheContract" )]
    public interface IClientContractAsynchronous
    {
        [OperationContract]
        Task<TResponse> SendReceiveAsync( TRequest req );
    }

    [ServiceContract( Namespace="X", Name="TheContract" )]
    public interface IServiceContractSynchronous
    {
        [OperationContract]
        TResponse SendReceive( TRequest req );
    }

Интерфейс клиента напрямуюожидаемые:

   var response = await client.Channel.SendReceiveAsync( request );

Невозможно использовать параметры out или ref в контракте об операциях.Все данные ответа должны быть переданы в возвращаемом значении.Это на самом деле было для меня серьезным изменением.
Я использую этот интерфейс в AsyncWcfLib , он поддерживает Модель программирования на основе актера .

2 голосов
/ 30 августа 2011

Как упоминал Мэтт, существует метод TaskFactory.FromAsync, который позволяет вам создать Task из пары Begin / End. Когда вы добавляете ссылку на WCF, вам нужно включить асинхронные конечные точки, а затем вы можете сами их обернуть, используя методы расширения.

Как упомянул Amadeo, есть пример этого в Async CTP, в каталоге (C# WCF) Stock Quotes.

Также в этом каталоге находится проект TaskWsdlImportExtension. Добавьте ссылку на эту DLL и измените ваш .config следующим образом:

<configuration>
 <system.serviceModel>
  <client>
   <metadata>
    <wsdlImporters>
     <extension type="TaskWsdlImportExtension.TaskAsyncWsdlImportExtension, TaskWsdlImportExtension" />
    </wsdlImporters>
   </metadata>
  </client>
 </system.serviceModel>
</configuration>

Тогда вам совсем не нужно делать свою собственную обертку; TaskWsdlImportExtension сделает это за вас.

1 голос
/ 09 августа 2012

Вы справедливо указываете, что async / await построены вокруг методов, возвращающих Task и Task (отличное объяснение работы async / await см. здесь ).Вот как сгенерировать методы на основе задач для службы WCF:

  1. В Visual Studio 2012 RC есть дополнительный флажок в диалоговом окне «Настроить ссылку на службу»: «Создать операции на основе задач»,Хотя я не вижу этой опции, описанной в MSDN , я ожидаю, что она существует специально для обеспечения бесшовной асинхронизации / ожидания для вызовов WCF.

  2. Для более ранних версий взгляните на этот пост , описывающий расширение, позволяющее генерировать методы на основе Task <> в WCF даже с CTP.

...