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 itsAsynchronousSendEnabled
property totrue
. 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.
In Windows Communication Foundation (WCF) applications, a service operation can be implemented asynchronously or synchronously without dictating to the client how to call it.
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.
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.
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.
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 :)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With