Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous Streaming in WCF

I am working with Streaming with WCF and I have a question about what the paragraph on "Enabling Asynchronous Streaming" means from the MSDN article on Large Data and Streaming in WCF.

To enable asynchronous streaming, add the DispatcherSynchronizationBehavior endpoint behavior to the service host and set its AsynchronousSendEnabled property to true. We have also added the capability of true asynchronous streaming on the send side. This improves scalability of the service in scenarios where it is streaming messages to multiple clients some of which are slow in reading possibly due to network congestion or are not reading at all. In these scenarios we now do not block individual threads on the service per client. This ensures that the service is able to process many more clients thereby improving the scalability of the service.

I understand that the above means I add

<behaviors>
  <endpointBehaviors>
    <behavior name="AsyncStreaming">
      <dispatcherSynchronization asynchronousSendEnabled="true" />
    </behavior>
  </endpointBehaviors>
  ...

To my web.config file and referencing the AsyncStreaming behavior in my endpoint, however I don't understand what doing those steps accomplishes for me. Do I need to modify my code at all to take advantage of this asynchronousness?

Also on a similar topic (but if it is too different I will move it to a new question), how does using async/await effect using Streams in WCF? Can I do Task<Stream> Foo() in my service contract? I make some database calls whose results I eventually wrap in to a custom stream that I will be returning from the WCF service. Being able to use things like ExecuteDataReaderAsync() is very useful, can I still use it when dealing with streamed instead of buffered messages?

I have tested it and I know it "works" using Tasks but I don't know if doing it causes the function to fall back to "Buffered" mode like when you provide more than one parameter to the function (See the 3rd paragraph of "Programming Model for Streamed Transfers" on the same MSDN page) and I don't know how to check to see if that is happening.

like image 757
Scott Chamberlain Avatar asked Apr 17 '14 02:04

Scott Chamberlain


People also ask

Is WCF asynchronous?

In Windows Communication Foundation (WCF) applications, a service operation can be implemented asynchronously or synchronously without dictating to the client how to call it.

What is streaming in WCF?

Windows Communication Foundation (WCF) can send messages using either buffered or streamed transfers. In the default buffered-transfer mode, a message must be completely delivered before a receiver can read it. In streaming transfer mode, the receiver can begin to process the message before it is completely delivered.

Are streams asynchronous?

A stream is a sequence of asynchronous events. It is like an asynchronous Iterable—where, instead of getting the next event when you ask for it, the stream tells you that there is an event when it is ready.

What is WCF service?

Windows Communication Foundation (WCF) is a framework for building service-oriented applications. Using WCF, you can send data as asynchronous messages from one service endpoint to another. A service endpoint can be part of a continuously available service hosted by IIS, or it can be a service hosted in an application.


2 Answers

I traced it down to RequestContext via the .NET Reference Source. Apparently, the ChannelHandler.sendAsynchronously field controls whether the message reply is done asynchronously (via RequestContext.BeginReply/EndReply APM methods) or synchronously via RequestContext.Reply.

As far as I can tell, all this does is frees a server-side thread which is returned to the pool, and which otherwise would be busy inside RequestContext.Reply with "pumping" the stream to the client, for as long as the Stream object is alive on the server.

This appears to be totally transparent, so I think you can safely use async TAP-based contract methods and return Task<Stream>. In another contract method you could do await Stream.WriteAsync, for example.

Please share your actual experience as your own answer when you get there, I'd be very interested in the details :)

like image 59
noseratio Avatar answered Sep 30 '22 04:09

noseratio


Good question on a complex topic. I've implemented a streaming WCF service to accommodate huge (up to 2GB) downloads, but I'm a bit confused, too, about this AsyncStreaming=True business since WCF is already asynchronous (in that each connected client gets its own thread and requests and receives asynchronously) as long as

 <ServiceBehavior(ConcurrencyMode:=ConcurrencyMode.Multiple, InstanceContextMode:=InstanceContextMode.PerCall)>

But you do have to alter your code to make streaming work. Even if you have Binding.TransferMode = TransferMode.Streamed , the program will revert to buffering if you don't change the code so that your uploading and downloading functions A) get and return streams and B) your upload and download functions implements something like this:

//oBuffer is your content
if (oBuffer != null) {
    oStream = new MemoryStream(oBuffer);

    if (oStream.CanSeek) {
        oStream.Seek(0, SeekOrigin.Begin);
    }
    return oStream;
}

This is a decent HowTo article I used as a guide: http://www.codeproject.com/Articles/166763/WCF-Streaming-Upload-Download-Files-Over-HTTP

like image 32
Brian Avatar answered Sep 30 '22 05:09

Brian