C# Async CTP-如何使用Async/await调用wcf服务?

C# Async CTP-如何使用Async/await调用wcf服务?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,如果调用WCF服务方法,我会执行以下操作: proxy.DoSomethingAsync(); proxy.DoSomethingAsyncCompleted += OnDoSomethingAsyncCompleted; 如何使用新的asyncctp实现同样的功能? 我想我需要类似于proxy.DoSomethingTaskAsync或proxy.DoSomethingAsync().ToTask()之类的东西?web服务调用需要返回一个任务才能使用等待关键字,但是如何使用???在CTP中,

如果调用WCF服务方法,我会执行以下操作:

proxy.DoSomethingAsync();
proxy.DoSomethingAsyncCompleted += OnDoSomethingAsyncCompleted;
如何使用新的
async
ctp实现同样的功能?
我想我需要类似于
proxy.DoSomethingTaskAsync
proxy.DoSomethingAsync().ToTask()之类的东西?web服务调用需要返回一个
任务
才能使用
等待
关键字,但是如何使用???

在CTP中,有一些工厂方法可以将常规APM函数(开始/结束)转换为与新的异步关键字兼容的函数,例如:

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);

有关更多信息,请参见CTP讨论组上的

异步CTP中有一个WCF示例,它将向您展示如何在WCF中使用异步/等待模型

关于在WCF中支持此模型的计划,您可以查看以下帖子:

希望这有帮助


Amadeo

如Matt所述,有一个
任务工厂.FromAsync
方法,允许您从
开始
/
结束
对创建
任务
。在添加WCF引用时,需要启用异步端点,然后可以使用扩展方法将它们封装起来

正如Amadeo所提到的,在Async CTP的
(C#WCF)股票报价
目录下有一个例子

在该目录中还有一个
TaskWsdlImportExtension
项目。添加对该dll的引用并修改.config,如下所示:

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


这样你就不必自己包装了;
任务wsdlimportextension
将为您完成此任务。

异步客户端调用同步服务是很常见的。
以下客户端和服务合同匹配(在幕后使用了一些魔术):

无法在操作合同中使用out或ref参数。必须在返回值中传递所有响应数据。这对我来说确实是一个突破性的变化。

我在中使用此接口,它支持。

使用async await的异步服务响应速度非常快,因为它可以交错许多客户端调用并并行执行它们(2)。 尽管如此,该服务可以在一个线程(3)上完全线程安全地运行,并且可以是单例服务(1)或框架为会话或调用创建的服务对象

实施服务时,请注意ServiceBehavior属性(1)…(3):

无法在运行合同中使用out或ref参数。所有响应数据必须由返回值任务(T)传递。

我在中使用此接口,它支持。

您正确地指出,async/await是围绕返回Task和Task的方法构建的(有关async/await工作原理的详细说明,请参阅)。以下是如何为WCF服务生成基于任务的方法:

  • Visual Studio 2012 RC在“配置服务引用”对话框中有一个附加复选框:“生成基于任务的操作”。虽然我在中没有看到该选项的文档,但我希望它的存在是为了允许WCF调用上的无缝异步/等待

  • 对于早期版本,请看,其中描述了一个扩展,该扩展允许在使用CTP的情况下基于WCF生成基于任务的方法


  • 谢谢你的回答,但我还是不明白。正如您在示例中所示,我理解这对流读取的作用,但如何将其应用于wcf服务调用?生成的代理将具有BeginDoSomething/EndDoSomething方法(前提是您将正确的选项传递给svcutil/wizards)。太糟糕了,这些功能还不可用。您是否应该将2个答案合并为1?
    <configuration>
     <system.serviceModel>
      <client>
       <metadata>
        <wsdlImporters>
         <extension type="TaskWsdlImportExtension.TaskAsyncWsdlImportExtension, TaskWsdlImportExtension" />
        </wsdlImporters>
       </metadata>
      </client>
     </system.serviceModel>
    </configuration>
    
        [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 );
    
        [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( ... );
            }
        }
    
       var response = await client.Channel.SendReceiveAsync( request );