简体   繁体   中英

Calling async WCF method synchronously WITHOUT ServiceReference

I have a self-hosted WCF service, .NET framework 4.5.2, using NetTcpBinding, and a WPF client (4.5.2 also) consuming this service remotely. Thus far, all of my OperationContracts have been synchronous.

I want to add an asynchronous OperationContract to the WCF service, but call it synchronously from the client (the reason for this is so I can use async/await inside the service method).

The catch: this solution doesn't use service references or SvcUtil. We're using the shared library pattern where the service contracts are defined in a shared library referenced by both the client and server. Client proxies are created using ChannelFactory.CreateChannel.

Is that even feasible? I need to keep async/await out of the client but use it in the server method. If it's not possible, can I make the OperationContract synchronous but treat it like a Main method and use GetAwaiter().GetResult(), or will I run into deadlock issues?

Unfortunately the 3 separate ways of declaring your server's OperationContract create different interface signatures in your service contract assembly:

  • Plain synchronous FooResponse Foo(FooRequest)
  • APM asynchronous IAsyncResult BeginFoo(FooRequest) / FooResponse EndFoo(IAsyncResult)
  • TAP asynchronous Task<FooResponse> FooAsync(FooRequest)

However, WCF treats these all the same "on the wire". Add Service Reference is able to automagically convert the ServiceContract to a copy (in reference.cs) that supports the style needed for the client.

In your case, if you just switched your server to use TAP async, the client code would have to change to use .Wait() \\ .Result and maybe some .ConfigureAwait(false) depending on the app.

With some hints from this answer there is an easier way:

  • Retain the current synchronous service contract
  • Create a new async version of the whole service contract as <Name>Async but keep the same service contract attributes and operations
  • Switch all the operation methods to the FooAsync style above
  • Specify ServiceContact.Name as the same as the old service contract if the Name was implicit
  • Change your server to implement the Async version of the service contract not the synchronous one

Your client can then continue to use the original synchronous interface talking to the old or new server.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM