{"id":56007,"date":"2012-04-06T17:32:26","date_gmt":"2012-04-06T17:32:26","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2012\/04\/06\/overriding-stream-asynchrony\/"},"modified":"2012-04-06T17:32:26","modified_gmt":"2012-04-06T17:32:26","slug":"overriding-stream-asynchrony","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/overriding-stream-asynchrony\/","title":{"rendered":"Overriding Stream Asynchrony"},"content":{"rendered":"<p>In .NET 4.5 Beta, the Stream class provides multiple virtual methods related to reading and writing:<\/p>\n<ul>\n<li>Read, BeginRead \/ EndRead, ReadAsync<\/li>\n<li>Write, BeginWrite \/ EndWrite, WriteAsync<\/li>\n<li>Flush, FlushAsync<\/li>\n<li>CopyToAsync<\/li>\n<\/ul>\n<p>As a developer deriving from Stream, it&rsquo;s helpful to understand what the base implementations do and when you can and should override them.<\/p>\n<p><strong>Read, Write, Flush<\/strong><\/p>\n<p>The Read, Write, and Flush methods are the core synchronous mechanisms from reading and writing from and to a stream:<\/p>\n<blockquote>\n<p><font face=\"Consolas\">public abstract int Read(&nbsp; byte[] buffer, int offset, int count);       <br>public abstract void Write(byte[] buffer, int offset, int count);        <br>public abstract void Flush();<\/font><\/p>\n<\/blockquote>\n<p>You must override these methods. This isn&rsquo;t just guidance: the methods are abstract, and thus all valid derivations must override them.&nbsp; If your stream is only readable or only writable, or if you wanted to prohibit synchronous usage, you could choose to throw a NotSupportedException from the methods you don&rsquo;t want consumers to be using, but you still must override the methods.<\/p>\n<p><strong>BeginRead\/EndRead, BeginWrite\/EndWrite<\/strong><\/p>\n<p>Since the early days of .NET, Stream has supported asynchronous reading and writing via the following methods that conform to the APM pattern:<\/p>\n<blockquote>\n<p><font face=\"Consolas\">public virtual IAsyncResult BeginRead(       <br>&nbsp;&nbsp;&nbsp; byte[] buffer, int offset, int count, AsyncCallback callback, object state);        <br>public virtual int EndRead(IAsyncResult asyncResult);<\/font><\/p>\n<p>   <font face=\"Consolas\"><\/font>    <\/p>\n<p><font face=\"Consolas\">public virtual IAsyncResult BeginWrite(       <br>&nbsp;&nbsp;&nbsp; byte[] buffer, int offset, int count, AsyncCallback callback, object state);        <br>public virtual void EndWrite(IAsyncResult asyncResult);<\/font><\/p>\n<\/blockquote>\n<p>If you don&rsquo;t override BeginRead\/EndRead or BeginWrite\/EndWrite, their default implementation in the Stream class will simply queue up work to the ThreadPool to call the corresponding synchronous Read\/Write method. This means that, by default, these Begin\/End methods will be doing their work asynchronously with regards to the caller, but for the duration of the actual read or write operation, a thread from the ThreadPool will be blocked (see my previous blog post on <a href=\"https:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2012\/03\/24\/10287244.aspx\">offloading vs scalability<\/a>). If you can provide a truly asynchronous implementation, one based on async I\/O that won&rsquo;t block threads while I\/O operations are in progress, you should consider overriding these methods.&nbsp; <\/p>\n<p><strong>ReadAsync, WriteAsync, <strong>FlushAsync<\/strong><\/strong><\/p>\n<p>New to .NET 4.5, the Stream class provides three virtual methods for reading and writing asynchronously based on the <a href=\"https:\/\/www.microsoft.com\/download\/en\/details.aspx?id=19957\">Task-based Asynchronous Pattern<\/a>:<\/p>\n<blockquote>\n<p><font face=\"Consolas\">public virtual Task&lt;int&gt; ReadAsync(       <br>&nbsp;&nbsp;&nbsp; <\/font><font face=\"Consolas\">byte[] buffer, int offset, int count, CancellationToken cancellationToken);       <br>public virtual Task WriteAsync(        <br>&nbsp;&nbsp;&nbsp; byte[] buffer, int offset, int count, CancellationToken cancellationToken);        <br><\/font><font face=\"Consolas\">public virtual Task FlushAsync(CancellationToken cancellationToken);<\/font><\/p>\n<\/blockquote>\n<p>If you don&rsquo;t override ReadAsync or WriteAsync, their default implementation in the Stream class will simply use the BeginRead\/EndRead or BeginWrite\/EndWrite methods to perform the work, returning a Task&lt;int&gt; or Task to represent those calls, in a manner extremely similar to how Task.Factory.FromAsync creates Tasks from Begin\/End pairs. So, if you only override the synchronous methods and none of the asynchronous ones, ReadAsync\/WriteAsync will return a Task that represents Read\/Write running on the ThreadPool, via the default implementation of BeginRead\/EndRead\/BeginWrite\/EndWrite. If you have overridden BeginRead\/EndRead\/BeginWrite\/EndWrite, then ReadAsync\/WriteAsync will pick up that custom implementation and use it for its asynchrony. You can of course override ReadAsync\/WriteAsync as well, regardless of whether you&rsquo;ve overridden the Begin\/End methods; this is in particular a good idea if you are able to support cancellation throughout the processing of the asynchronous operation, since the XxAsync methods accept a CancellationToken.<\/p>\n<p>In some cases, you may have found it too difficult or error prone to implement the Begin\/End methods, even if an asynchronous implementation would have been possible.&nbsp; In such cases, you might consider overriding ReadAsync\/WriteAsync without overriding the Begin\/End methods. This will typically be made significantly easier via the C# and Visual Basic support for writing async methods using await.&nbsp; Then, once you have your Task-based implementations, you might even consider overriding the Begin\/End methods and implementing them <a href=\"https:\/\/blogs.msdn.com\/b\/pfxteam\/archive\/2011\/06\/27\/10179452.aspx\">in terms of the Task-based methods<\/a>.<\/p>\n<p>The FlushAsync method is the asynchronous counterpart to the synchronous Flush method. The base implementation of Stream.FlushAsync queues to the ThreadPool a call to Flush. If your Stream has a nop Flush method, it&rsquo;s a good idea to override FlushAsync to simply return an already completed task, as there&rsquo;s no need to spend energy queueing a work item that itself will be a nop.&nbsp; Of course, if you can implement FlushAsync using async I\/O rather than burning a ThreadPool thread while invoking the synchronous variant, that&rsquo;s a good thing to consider doing.<\/p>\n<p><strong>CopyToAsync<\/strong><\/p>\n<p>.NET 4.5 also includes a virtual, asynchronous counterpart to the synchronous (non-virtual) CopyTo method that was introduced in .NET 4:<\/p>\n<blockquote>\n<p><font face=\"Consolas\">public virtual Task CopyToAsync(       <br>&nbsp;&nbsp;&nbsp; Stream destination, int bufferSize, CancellationToken cancellationToken);<\/font><\/p>\n<\/blockquote>\n<p>The base Stream.CopyToAsync method uses the ReadAsync method on the source stream and the WriteAsync method on the destination stream, calling them in a loop to transfer data from one stream to the other.&nbsp; However a derived type could choose to override CopyToAsync to provide a more specialized implementation.&nbsp; For example, MemoryStream already has all of its data buffered in memory, so it can achieve the copy with a single WriteAsync of the entire buffer to the target stream, or even a straight buffer copy if the target is also a MemoryStream.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In .NET 4.5 Beta, the Stream class provides multiple virtual methods related to reading and writing: Read, BeginRead \/ EndRead, ReadAsync Write, BeginWrite \/ EndWrite, WriteAsync Flush, FlushAsync CopyToAsync As a developer deriving from Stream, it&rsquo;s helpful to understand what the base implementations do and when you can and should override them. Read, Write, Flush [&hellip;]<\/p>\n","protected":false},"author":360,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7908],"tags":[7925,36,7909,7912],"class_list":["post-56007","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-net-4-5","tag-async","tag-parallel-extensions","tag-task-parallel-library"],"acf":[],"blog_post_summary":"<p>In .NET 4.5 Beta, the Stream class provides multiple virtual methods related to reading and writing: Read, BeginRead \/ EndRead, ReadAsync Write, BeginWrite \/ EndWrite, WriteAsync Flush, FlushAsync CopyToAsync As a developer deriving from Stream, it&rsquo;s helpful to understand what the base implementations do and when you can and should override them. Read, Write, Flush [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56007","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/360"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=56007"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56007\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=56007"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=56007"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=56007"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}