Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async CTP - How can I use async/await to call a wcf service?

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??

like image 702
Roger Avatar asked Nov 04 '10 09:11

Roger


People also ask

How do you call async method in WCF?

To call a WCF service method asynchronously you need to create an AsyncCallback delegate and pass this delegate to the asynchronous proxy method. Note that the AsyncCallback delegate is executed on a worker thread and so this doesn't block the main thread of the application.

What is async CTP?

The Async Community Technology Preview (CTP) is a freely available download for Visual Studio 2010. The Async CTP includes the async and await keywords that are being considered for the next iterations of C# and VB.NET.

Does async await use thread pool?

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active.

Does async await make code synchronous?

Async/await helps you write synchronous-looking JavaScript code that works asynchronously. Await is in an async function to ensure that all promises that are returned in the function are synchronized. With async/await, there's no use of callbacks.


2 Answers

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

like image 177
Matt Warren Avatar answered Oct 03 '22 23:10

Matt Warren


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.

like image 43
Stefan Forster Avatar answered Oct 04 '22 00:10

Stefan Forster