异步 CTP - 如何使用 async/await 调用 wcf 服务?

发布于 2024-09-30 06:08:59 字数 394 浏览 4 评论 0原文

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

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

How can I do the same using the new async ctp? 我想我需要像 proxy.DoSomethingTaskAsyncproxy.DoSomethingAsync().ToTask() 之类的东西? Web 服务调用需要返回一个 Task 才能使用 await 关键字,但是如何呢?

If I call a WCF service method I would do something like this:

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

How could I do the same using the new async ctp?
I guess I would need something like proxy.DoSomethingTaskAsync or proxy.DoSomethingAsync().ToTask()? The web service call needs to return a Task<T> to be able to use the await keyword, but how??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

想念有你 2024-10-07 06:08:59

在 CTP 中,有一些工厂方法可以将常规 APM 函数(开始/结束)转换为与新的 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 讨论组上了解更多信息

In the CTP there are factory methods that do the work of turning regular APM functions (Begin/End) into ones that are compatible with the new async keyword, for instance:

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

So in your case you can do the equivalent and then you'd then call it like so:

async proxy.DoSomethingTaskAsync()

See this thread on the CTP discussion group for more info

一江春梦 2024-10-07 06:08:59

使用 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( ... );
        }
    }

要在一个线程上运行每个调用,在您 Open() ServiceHost 时必须存在 System.Threading.SynchronizationContext.Current != null 。
使用 SynchronizationContext,您无需关心锁。原子的、不可中断的代码段大致从一个等待延伸到下一个等待。
请注意,共享服务数据在每次等待时都处于一致状态,并注意来自一个客户端的连续请求可能不会按照发送的顺序进行响应。

在客户端,异步服务操作是可等待的:

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

不可能在操作契约中使用 outref 参数。所有响应数据必须通过返回值Task(T)传递。
我在 AsyncWcfLib 中使用此接口,它支持 基于 Actor 的编程模型

An asynchronous service using async-await is very responsive as it can interleave many client calls and execute them in parallel (2).
Despite this, the service can run fully thread-safe on one thread (3) and can be a singleton service (1) or a service object created by the framework for a session or a call only.

When implementing the service, please note the 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( ... );
        }
    }

To run every call on one thread, a System.Threading.SynchronizationContext.Current != null must be present at the moment you Open() the ServiceHost.
Using the SynchronizationContext, you need not to care about locks. Atomic, non interruptable code sections stretch roughly from one await to the next.
Take care that shared service data is in a consistent state at every await and be aware that successive requests from one client may be responded not in the order they where sent.

On client side, the asynchronous service operation is awaitable:

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

It is not possible to use out or ref parameters in the operation contract. All response data must be passed by the returned value Task(T).
I use this interface in AsyncWcfLib, it supports a Actor based programming model.

找个人就嫁了吧 2024-10-07 06:08:59

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

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

链接

希望这有帮助。

阿马德奥

There is a WCF sample in the Async CTP that will show you how to use the async/await model in WCF.

In terms of plans for supporting this model in WCF, you can take a look at the following post:

Link

Hope this helps.

Amadeo

盛夏已如深秋| 2024-10-07 06:08:59

正如 Matt 提到的,有一个 TaskFactory.FromAsync 方法允许您从 Begin/End 创建一个 Task代码>对。添加 WCF 引用时需要启用异步端点,然后您可以使用扩展方法自行包装它们。

正如 Amadeo 提到的,异步 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 将为您完成此操作。

As mentioned by Matt, there is a TaskFactory.FromAsync method that allows you to create a Task from a Begin/End pair. You need to enable asynchronous endpoints when you add your WCF reference, and then you can wrap them up yourself using extension methods.

As mentioned by Amadeo, there is a sample of this in the Async CTP, under the (C# WCF) Stock Quotes directory.

Also in that directory, there is a TaskWsdlImportExtension project. Add a reference to that dll and modify your .config as such:

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

Then you don't have to do your own wrapping at all; the TaskWsdlImportExtension will do it for you.

断念 2024-10-07 06:08:59

异步客户端调用同步服务是很常见的。
以下客户端和服务契约匹配(在幕后使用的一点魔法):

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

不可能在经营合同。所有响应数据都必须在返回值中传递。这对我来说实际上是一个突破性的改变。
我在 AsyncWcfLib 中使用此接口,它支持 基于 Actor 的编程模型

It is quite common to have asynchronous clients calling a synchronous service.
The following client and service contracts match (a bit magic used behind the scenes):

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

The client interface is directly awaitable:

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

It is not possible to use out or ref parameters in the operaton contract. All response data must be passed in the return value. This actually was a breaking change for me.
I use this interface in AsyncWcfLib, it supports a Actor based programming model.

长亭外,古道边 2024-10-07 06:08:59

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

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

  2. 对于早期版本,请查看 这篇文章,描述了一个允许生成任务<>的扩展基于 WCF 的方法,甚至使用 CTP。

You rightly point out that async/await are built around methods returning Task and Task (for a great explanation of the working of async/await, see here). Here's how to generate Task based methods for a WCF service:

  1. Visual Studio 2012 RC has an additional check-box in the "Configure Service Reference" dialog box: "Generate task based operations". While I don't see that option documented in the MSDN, I expect it exists specifically to allow seamless async/await on WCF calls.

  2. For earlier versions, take a look at this post, describing an extension which allows generating Task<> based methods on WCF even with the CTP.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文