WCF中的单向异步/等待调用

6

我有一个遗留的WCF服务,其中有许多按最经典的方式实现的单向操作契约:

    // The interface
    [OperationContract(IsOneWay = true, AsyncPattern = true)]
    IAsyncResult BeginFinalizePublishing(PageContent pageContent, AsyncCallback callback, object asyncState);
    void EndFinalizePublishing(IAsyncResult result);

    // The service
    public IAsyncResult BeginFinalizePublishing(PageContent pageContent, AsyncCallback callback, object asyncState)
    {...}

目前一切都运行良好,现在我需要将它转换为c# 5的最新async/await模式。请注意操作的单向性质。我的问题:

  • 我想我需要从 OperationContract 属性中删除 AsyncPattern = true
  • 将接口中的 IAsyncResult 返回类型替换为 void ,并在类中使用 async void
  • 出于方便起见,删除Begin/End并添加Async后缀。

那么客户端应该如何调用单向操作? 对于单向调用,在客户端不需要使用async/await吗?

这样做是否正确,并且将在客户端上实现真正的异步处理。

    // The proxy
    public void FinalizePublishingAsync(PageContent pageContent)
    {
        Channel.FinalizePublishingAsync(pageContent);
    }

        // The consumer of the client
        // No way to use await for void methods. 
        IComPublisherFinalizerClient cl = new IComPublisherFinalizerClient();
        cl.FinalizePublishingAsync(content); 
        cl.Close();
1个回答

6
首先,客户端完全独立于服务器。客户端或服务器可以是同步的,使用 IAsyncResult(APM)异步代码,或使用 async(TAP)异步代码。
其次,服务器端的 async 方法应返回 Task,即使是单向通信也应如此。一个返回 void 的同步方法的 async 等价方法是一个 async Task 方法,而不是一个 async void 方法。在 WCF 服务中使用 async void 特别危险,因为它可能违反 ConcurrencyMode
所以你的服务器端步骤应该像这样:
  • 删除 OperationContract.AsyncPattern
  • Begin*/End* 方法对合并为一个返回 Task*Async 方法。
客户端应在其代理接口上看到返回 Task 的方法,并使用 await。这并不意味着您正在等待响应;这个 await 使您能够等待实际消息发送(如果有延迟),并检测通道通信错误(如果您使用可靠通道)。

Stephen,感谢您的回复。单向调用没有回复消息,并且在服务器收到请求之前等待 - 这就是为什么它们被标记为void的原因。但是据我所知(Juval写过这个问题),服务器实际上确实会发送一个简短的回复消息,说明客户端请求已排队。IAsyncResult解决了这个问题。您想说即使操作(标记为OneWay)返回一个任务,调用者也不会被阻塞直到服务器的回复吗?还是它将像常规的OneWay操作一样阻塞,直到服务器的回复? - Zara
它将充当常规的单向操作。因此它不会等待服务器方法完成(或被调用),也不会报告来自服务器的错误。 - Stephen Cleary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接