Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One-way async/await calls in WCF

I have a legacy WCF service with a number of One-Way operation contracts implemented in the most classic way:

    // 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)
    {...}

So everything works fine here, now I need to convert this to c# 5 latest async/await pattern. Pay attention to the one way nature of the operations. My questions:

  • I guess I need to remove the AsyncPattern = true from the OperationContract attribute.
  • Replace the IAsyncResult return type with the void in the interface and async void in the class.
  • Remove the Begin/End and add the Async postfix for the sake of convenience.

Now how should I call the one-way operation from the client? No usage of async/await on the client-side right for one-way calls?

Is this correct and will result in a true asynchronous processing on the client side.

    // 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();
like image 965
Zara Avatar asked Mar 13 '13 12:03

Zara


1 Answers

First off, the client is entirely separate from the server. Either client or server may be synchronous, use IAsyncResult (APM) asynchronous code, or use async (TAP) asynchronous code.

Secondly, async methods on the server side should return Task, even for one-way communications. The async equivalent of a synchronous method returning void is an async Task method, not an async void method. async void is especially dangerous in WCF services since it may violate the ConcurrencyMode.

So your server-side steps would look like this:

  • Remove OperationContract.AsyncPattern.
  • Combine the Begin*/End* method pair into a single *Async method which returns Task.

Your client side should see Task-returning methods on the interface for its proxy, which it should await. This does not mean that you're waiting for a response; this await enables you to wait for the actual message to be sent (if there are delays) and detect channel communications errors (if you are using a reliable channel).

like image 136
Stephen Cleary Avatar answered Oct 06 '22 00:10

Stephen Cleary