{"id":20679,"date":"2018-11-07T10:00:31","date_gmt":"2018-11-07T17:00:31","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/dotnet\/?p=20085"},"modified":"2025-03-15T16:03:24","modified_gmt":"2025-03-15T23:03:24","slug":"understanding-the-whys-whats-and-whens-of-valuetask","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/understanding-the-whys-whats-and-whens-of-valuetask\/","title":{"rendered":"Understanding the Whys, Whats, and Whens of ValueTask"},"content":{"rendered":"<p>The .NET Framework 4 saw the introduction of the\u00a0<code>System.Threading.Tasks<\/code>\u00a0namespace, and with it the\u00a0<code>Task<\/code>\u00a0class. This type and the derived\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0have long since become a staple of .NET programming, key aspects of the asynchronous programming model introduced with C# 5 and its\u00a0<code>async<\/code>\u00a0\/\u00a0<code>await<\/code>\u00a0keywords. In this post, I&#8217;ll cover the newer\u00a0<code>ValueTask<\/code>\/<code>ValueTask&lt;TResult&gt;<\/code>\u00a0types, which were introduced to help improve asynchronous performance in common use cases where decreased allocation overhead is important.<\/p>\n<h2>Task<\/h2>\n<p><code>Task<\/code>\u00a0serves multiple purposes, but at its core it&#8217;s a &#8220;promise&#8221;, an object that represents the eventual completion of some operation. You initiate an operation and get back a\u00a0<code>Task<\/code>\u00a0for it, and that\u00a0<code>Task<\/code>\u00a0will complete when the operation completes, which may happen synchronously as part of initiating the operation (e.g. accessing some data that was already buffered), asynchronously but complete by the time you get back the\u00a0<code>Task<\/code>\u00a0(e.g. accessing some data that wasn&#8217;t yet buffered but that was very fast to access), or asynchronously and complete after you&#8217;re already holding the\u00a0<code>Task<\/code>\u00a0(e.g. accessing some data from across a network). Since operations might complete asynchronously, you either need to block waiting for the results (which often defeats the purpose of the operation having been asynchronous to begin with) or you need to supply a callback that&#8217;ll be invoked when the operation completes. In .NET 4, providing such a callback was achieved via\u00a0<code>ContinueWith<\/code>\u00a0methods on the\u00a0<code>Task<\/code>, which explicitly exposed the callback model by accepting a delegate to invoke when the\u00a0<code>Task<\/code>\u00a0completed:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">SomeOperationAsync().ContinueWith(task =&gt;\r\n{\r\n    try\r\n    {\r\n        TResult result = task.Result;\r\n        UseResult(result);\r\n    }\r\n    catch (Exception e)\r\n    {\r\n        HandleException(e);\r\n    }\r\n});<\/pre>\n<\/div>\n<p>But with the .NET Framework 4.5 and C# 5,\u00a0<code>Task<\/code>s could simply be\u00a0<code>await<\/code>ed, making it easy to consume the results of an asynchronous operation, and with the generated code being able to optimize all of the aforementioned cases, correctly handling things regardless of whether the operation completes synchronously, completes asynchronously quickly, or completes asynchronously after already (implicitly) providing a callback:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">TResult result = await SomeOperationAsync();\r\nUseResult(result);<\/pre>\n<\/div>\n<p><code>Task<\/code>\u00a0as a class is very flexible and has resulting benefits. For example, you can await it multiple times, by any number of consumers concurrently. You can store one into a dictionary for any number of subsequent consumers to await in the future, which allows it to be used as a cache for asynchronous results. You can block waiting for one to complete should the scenario require that. And you can write and consume a large variety of operations over tasks (sometimes referred to as &#8220;combinators&#8221;), such as a &#8220;when any&#8221; operation that asynchronously waits for the first to complete.<\/p>\n<p>However, that flexibility is not needed for the most common case: simply invoking an asynchronous operation and awaiting its resulting task:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">TResult result = await SomeOperationAsync();\r\nUseResult(result);<\/pre>\n<\/div>\n<p>In such usage, we don&#8217;t need to be able to await the task multiple times. We don&#8217;t need to be able to handle concurrent awaits. We don&#8217;t need to be able to handle synchronous blocking. We don&#8217;t need to write combinators. We simply need to be able to await the resulting promise of the asynchronous operation. This is, after all, how we write synchronous code (e.g.\u00a0<code>TResult result = SomeOperation();<\/code>), and it naturally translates to the world of\u00a0<code>async<\/code>\u00a0\/\u00a0<code>await<\/code>.<\/p>\n<p>Further,\u00a0<code>Task<\/code>\u00a0does have a potential downside, in particular for scenarios where instances are created\u00a0<em>a lot<\/em>\u00a0and where high-throughput and performance is a key concern:\u00a0<code>Task<\/code>\u00a0is a class. As a class, that means that any operation which needs to create one needs to allocate an object, and the more objects that are allocated, the more work the garbage collector (GC) needs to do, and the more resources we spend on it that could be spent doing other things.<\/p>\n<p>The runtime and core libraries mitigate this in many situations. For example, if you write a method like the following:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">public async Task WriteAsync(byte value)\r\n{\r\n    if (_bufferedCount == _buffer.Length)\r\n    {\r\n        await FlushAsync();\r\n    }\r\n    _buffer[_bufferedCount++] = value;\r\n}<\/pre>\n<\/div>\n<p>in the common case there will be space available in the buffer and the operation will complete synchronously. When it does, there&#8217;s nothing special about the\u00a0<code>Task<\/code>\u00a0that needs to be returned, since there&#8217;s no return value: this is the\u00a0<code>Task<\/code>-based equivalent of a\u00a0<code>void<\/code>-returning synchronous method. Thus, the runtime can simply cache a single non-generic\u00a0<code>Task<\/code>\u00a0and use that over and over again as the result task for any\u00a0<code>async Task<\/code>\u00a0method that completes synchronously (that cached singleton is exposed via `Task.CompletedTask`). Or for example, if you write:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">public async Task&lt;bool&gt; MoveNextAsync()\r\n{\r\n    if (_bufferedCount == 0)\r\n    {\r\n        await FillBuffer();\r\n    }\r\n    return _bufferedCount &gt; 0;\r\n}<\/pre>\n<\/div>\n<p>in the common case, we expect there to be some data buffered, in which case this method simply checks\u00a0<code>_bufferedCount<\/code>, sees that it&#8217;s larger than\u00a0<code>0<\/code>, and returns\u00a0<code>true<\/code>; only if there&#8217;s currently no buffered data does it need to perform an operation that might complete asynchronously. And since there are only two possible\u00a0<code>Boolean<\/code>\u00a0results (<code>true<\/code>\u00a0and\u00a0<code>false<\/code>), there are only two possible\u00a0<code>Task&lt;bool&gt;<\/code>\u00a0objects needed to represent all possible result values, and so the runtime is able to cache two such objects and simply return a cached\u00a0<code>Task&lt;bool&gt;<\/code>\u00a0with a\u00a0<code>Result<\/code>\u00a0of\u00a0<code>true<\/code>, avoiding the need to allocate. Only if the operation completes asynchronously does the method then need to allocate a new\u00a0<code>Task&lt;bool&gt;<\/code>, because it needs to hand back the object to the caller before it knows what the result of the operation will be, and needs to have a unique object into which it can store the result when the operation does complete.<\/p>\n<p>The runtime maintains a small such cache for other types as well, but it&#8217;s not feasible to cache everything. For example, a method like:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">public async Task&lt;int&gt; ReadNextByteAsync()\r\n{\r\n    if (_bufferedCount == 0)\r\n    {\r\n        await FillBuffer();\r\n    }\r\n\r\n    if (_bufferedCount == 0)\r\n    {\r\n        return -1;\r\n    }\r\n\r\n    _bufferedCount--;\r\n    return _buffer[_position++];\r\n}<\/pre>\n<\/div>\n<p>will also frequently complete synchronously. But unlike the\u00a0<code>Boolean<\/code>\u00a0case, this method returns an\u00a0<code>Int32<\/code>\u00a0value, which has ~4 billion possible results, and caching a\u00a0<code>Task&lt;int&gt;<\/code>\u00a0for all such cases would consume potentially hundreds of gigabytes of memory. The runtime does maintain a small cache for\u00a0<code>Task&lt;int&gt;<\/code>, but only for a few small result values, so for example if this completes synchronously (there&#8217;s data in the buffer) with a value like 4, it&#8217;ll end up using a cached task, but if it completes synchronously with a value like 42, it&#8217;ll end up allocating a new\u00a0<code>Task&lt;int&gt;<\/code>, akin to calling\u00a0<code>Task.FromResult(42)<\/code>.<\/p>\n<p>Many library implementations attempt to mitigate this further by maintaining their own cache as well. For example, the\u00a0<code>MemoryStream.ReadAsync<\/code>\u00a0overload introduced in the .NET Framework 4.5 always completes synchronously, since it&#8217;s just reading data from memory.\u00a0<code>ReadAsync<\/code>\u00a0returns a\u00a0<code>Task&lt;int&gt;<\/code>, where the\u00a0<code>Int32<\/code>\u00a0result represents the number of bytes read.\u00a0<code>ReadAsync<\/code>\u00a0is often used in a loop, often with the number of bytes requested the same on each call, and often with\u00a0<code>ReadAsync<\/code>\u00a0able to fully fulfill that request. Thus, it&#8217;s common for repeated calls to\u00a0<code>ReadAsync<\/code>\u00a0to return a\u00a0<code>Task&lt;int&gt;<\/code>\u00a0synchronously with the same result as it did on the previous call. As such,\u00a0<code>MemoryStream<\/code>\u00a0maintains a cache of a single task, the last one it returned successfully. Then on a subsequent call, if the new result matches that of its cached\u00a0<code>Task&lt;int&gt;<\/code>, it just returns the cached one again; otherwise, it uses\u00a0<code>Task.FromResult<\/code>\u00a0to create a new one, stores that as its new cached task, and returns it.<\/p>\n<p>Even so, there are many cases where operations complete synchronously and are forced to allocate a\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0to hand back.<a id=\"user-content-valuetasktresult-and-synchronous-completion\" class=\"anchor\" href=\"https:\/\/github.com\/stephentoub\/dotnet-blog\/blob\/ff8b236a4867d0e1dfa34daae6f203c18c594a7d\/2018\/11-Nov\/valuetasks\/valuetasks.md#valuetasktresult-and-synchronous-completion\"><\/a><\/p>\n<h2>ValueTask &lt;TResult&gt; and synchronous completion<\/h2>\n<p>All of this motivated the introduction of a new type in .NET Core 2.0 and made available for previous .NET releases via a\u00a0<code>System.Threading.Tasks.Extensions<\/code>\u00a0NuGet package:\u00a0<code>ValueTask&lt;TResult&gt;<\/code>.<\/p>\n<p><code>ValueTask&lt;TResult&gt;<\/code>\u00a0was introduced in .NET Core 2.0 as a struct capable of wrapping either a\u00a0<code>TResult<\/code>\u00a0or a\u00a0<code>Task&lt;TResult&gt;<\/code>. This means it can be returned from an async method, and if that method completes synchronously and successfully, nothing need be allocated: we can simply initialize this\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0struct with the\u00a0<code>TResult<\/code>\u00a0and return that. Only if the method completes asynchronously does a\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0need to be allocated, with the\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0created to wrap that instance (to minimize the size of\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0and to optimize for the success path, an async method that faults with an unhandled exception will also allocate a\u00a0<code>Task&lt;TResult&gt;<\/code>, so that the\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0can simply wrap that\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0rather than always having to carry around an additional field to store an\u00a0<code>Exception<\/code>).<\/p>\n<p>With that, a method like\u00a0<code>MemoryStream.ReadAsync<\/code>\u00a0that instead returns a\u00a0<code>ValueTask&lt;int&gt;<\/code>\u00a0need not be concerned with caching, and can instead be written with code like:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">public override ValueTask&lt;int&gt; ReadAsync(byte[] buffer, int offset, int count)\r\n{\r\n    try\r\n    {\r\n        int bytesRead = Read(buffer, offset, count);\r\n        return new ValueTask&lt;int&gt;(bytesRead);\r\n    }\r\n    catch (Exception e)\r\n    {\r\n        return new ValueTask&lt;int&gt;(Task.FromException&lt;int&gt;(e));\r\n    }\r\n}<\/pre>\n<\/div>\n<h2>ValueTask &lt;TResult&gt; and asynchronous completion<\/h2>\n<p>Being able to write an async method that can complete synchronously without incurring an additional allocation for the result type is a big win. This is why\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0was added to .NET Core 2.0, and why new methods that are expected to be used on hot paths are now defined to return\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0instead of\u00a0<code>Task&lt;TResult&gt;<\/code>. For example, when we added a new\u00a0<code>ReadAsync<\/code>\u00a0overload to\u00a0<code>Stream<\/code>\u00a0in .NET Core 2.1 in order to be able to pass in a\u00a0<code>Memory&lt;byte&gt;<\/code>\u00a0instead of a\u00a0<code>byte[]<\/code>, we made the return type of that method be\u00a0<code>ValueTask&lt;int&gt;<\/code>. That way, Streams (which very often have a\u00a0<code>ReadAsync<\/code>\u00a0method that completes synchronously, as in the earlier\u00a0<code>MemoryStream<\/code>\u00a0example) can now be used with significantly less allocation.<\/p>\n<p>However, when working on very high-throughput services, we still care about avoiding as much allocation as possible, and that means thinking about reducing and removing allocations associated with asynchronous completion paths as well.<\/p>\n<p>With the\u00a0<code>await<\/code>\u00a0model, for any operation that completes asynchronously we need to be able to hand back an object that represents the eventual completion of the operation: the caller needs to be able to hand off a callback that&#8217;ll be invoked when the operation completes, and that requires having a unique object on the heap that can serve as the conduit for this specific operation. It doesn&#8217;t, however, imply anything about whether that object can be reused once an operation completes. If the object can be reused, then an API can maintain a cache of one or more such objects, and reuse them for serialized operations, meaning it can&#8217;t use the same object for multiple in-flight async operations, but it can reuse an object for non-concurrent accesses.<\/p>\n<p>In .NET Core 2.1,\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0was augmented to support such pooling and reuse. Rather than just being able to wrap a\u00a0<code>TResult<\/code>\u00a0or a\u00a0<code>Task&lt;TResult&gt;<\/code>, a new interface was introduced,\u00a0<code>IValueTaskSource&lt;TResult&gt;<\/code>, and\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0was augmented to be able to wrap that as well.\u00a0<code>IValueTaskSource&lt;TResult&gt;<\/code>\u00a0provides the core support necessary to represent an asynchronous operation to\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0in a similar manner to how\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0does:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">public interface IValueTaskSource&lt;out TResult&gt;\r\n{\r\n    ValueTaskSourceStatus GetStatus(short token);\r\n    void OnCompleted(Action&lt;object&gt; continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags);\r\n    TResult GetResult(short token);\r\n}<\/pre>\n<\/div>\n<p><code>GetStatus<\/code>\u00a0is used to satisfy properties like\u00a0<code>ValueTask&lt;TResult&gt;.IsCompleted<\/code>, returning an indication of whether the async operation is still pending or whether it&#8217;s completed and how (success or not).\u00a0<code>OnCompleted<\/code>\u00a0is used by the\u00a0<code>ValueTask&lt;TResult&gt;<\/code>&#8216;s awaiter to hook up the callback necessary to continue execution from an\u00a0<code>await<\/code>\u00a0when the operation completes. And\u00a0<code>GetResult<\/code>\u00a0is used to retrieve the result of the operation, such that after the operation completes, the awaiter can either get the\u00a0<code>TResult<\/code>\u00a0or propagate any exception that may have occurred.<\/p>\n<p>Most developers should never have a need to see this interface: methods simply hand back a\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0that may have been constructed to wrap an instance of this interface, and the consumer is none-the-wiser. The interface is primarily there so that developers of performance-focused APIs are able to avoid allocation.<\/p>\n<p>There are several such APIs in .NET Core 2.1. The most notable are\u00a0<code>Socket.ReceiveAsync<\/code>\u00a0and\u00a0<code>Socket.SendAsync<\/code>, with new overloads added in 2.1, e.g.<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">public ValueTask&lt;int&gt; ReceiveAsync(Memory&lt;byte&gt; buffer, SocketFlags socketFlags, CancellationToken cancellationToken = default);<\/pre>\n<\/div>\n<p>This overload returns a\u00a0<code>ValueTask&lt;int&gt;<\/code>. If the operation completes synchronously, it can simply construct a\u00a0<code>ValueTask&lt;int&gt;<\/code>\u00a0with the appropriate result, e.g.<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">int result = \u2026;\r\nreturn new ValueTask&lt;int&gt;(result);<\/pre>\n<\/div>\n<p>If it completes asynchronously, it can use a pooled object that implements this interface:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">IValueTaskSource&lt;int&gt; vts = \u2026;\r\nreturn new ValueTask&lt;int&gt;(vts);<\/pre>\n<\/div>\n<p>The\u00a0<code>Socket<\/code>\u00a0implementation maintains one such pooled object for receives and one for sends, such that as long as no more than one of each is outstanding at a time, these overloads will end up being allocation-free, even if they complete operations asynchronously. That&#8217;s then further surfaced through\u00a0<code>NetworkStream<\/code>. For example, in .NET Core 2.1,\u00a0<code>Stream<\/code>\u00a0exposes:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">public virtual ValueTask&lt;int&gt; ReadAsync(Memory&lt;byte&gt; buffer, CancellationToken cancellationToken);<\/pre>\n<\/div>\n<p>which\u00a0<code>NetworkStream<\/code>\u00a0overrides.\u00a0<code>NetworkStream.ReadAsync<\/code>\u00a0just delegates to\u00a0<code>Socket.ReceiveAsync<\/code>, so the wins from\u00a0<code>Socket<\/code>\u00a0translate to\u00a0<code>NetworkStream<\/code>, and\u00a0<code>NetworkStream.ReadAsync<\/code>\u00a0effectively becomes allocation-free as well.<\/p>\n<h2>Non-generic ValueTask<\/h2>\n<p>When\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0was introduced in .NET Core 2.0, it was purely about optimizing for the synchronous completion case, in order to avoid having to allocate a\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0to store the\u00a0<code>TResult<\/code>\u00a0already available. That also meant that a non-generic\u00a0<code>ValueTask<\/code>\u00a0wasn&#8217;t necessary: for the synchronous completion case, the\u00a0<code>Task.CompletedTask<\/code>\u00a0singleton could just be returned from a\u00a0<code>Task<\/code>-returning method, and was implicitly by the runtime for\u00a0<code>async Task<\/code>\u00a0methods.<\/p>\n<p>With the advent of enabling even asynchronous completions to be allocation-free, however, a non-generic\u00a0<code>ValueTask<\/code>\u00a0becomes relevant again. Thus, in .NET Core 2.1 we also introduced the non-generic\u00a0<code>ValueTask<\/code>\u00a0and\u00a0<code>IValueTaskSource<\/code>. These provide direct counterparts to the generic versions, usable in similar ways, just with a void result.<\/p>\n<h2>Implementing IValueTaskSource \/ IValueTaskSource&lt;T&gt;<\/h2>\n<p>Most developers should never need to implement these interfaces. They&#8217;re also not particularly easy to implement. If you decide you need to, there are several implementations internal to .NET Core 2.1 that can serve as a reference, e.g.<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/dotnet\/corefx\/blob\/61f51e6b2b26271de205eb8a14236afef482971b\/src\/System.Net.Sockets\/src\/System\/Net\/Sockets\/Socket.Tasks.cs#L808\"><code>AwaitableSocketAsyncEventArgs<\/code><\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/corefx\/blob\/89ab1e83a7e00d869e1580151e24f01226acaf3f\/src\/System.Threading.Channels\/src\/System\/Threading\/Channels\/AsyncOperation.cs#L37\"><code>AsyncOperation&lt;TResult&gt;<\/code><\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/corefx\/blob\/a10890f4ffe0fadf090c922578ba0e606ebdd16c\/src\/System.IO.Pipelines\/src\/System\/IO\/Pipelines\/Pipe.DefaultPipeReader.cs#L16\"><code>DefaultPipeReader<\/code><\/a><\/li>\n<\/ul>\n<p>To make this easier for developers that do want to do it, in .NET Core 3.0 we plan to introduce all of this logic encapsulated into a\u00a0<code>ManualResetValueTaskSourceCore&lt;TResult&gt;<\/code>\u00a0type, a struct that can be encapsulated into another object that implements\u00a0<code>IValueTaskSource&lt;TResult&gt;<\/code>\u00a0and\/or\u00a0<code>IValueTaskSource<\/code>, with that wrapper type simply delegating to the struct for the bulk of its implementation. You can learn more about this in the associated issue in the dotnet\/corefx repo at\u00a0<a href=\"https:\/\/github.com\/dotnet\/corefx\/issues\/32664\">https:\/\/github.com\/dotnet\/corefx\/issues\/32664<\/a>.<\/p>\n<h2>Valid consumption patterns for ValueTasks<\/h2>\n<p>From a surface area perspective,\u00a0<code>ValueTask<\/code>\u00a0and\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0are much more limited than\u00a0<code>Task<\/code>\u00a0and\u00a0<code>Task&lt;TResult&gt;<\/code>. That&#8217;s ok, even desirable, as the primary method for consumption is meant to simply be\u00a0<code>await<\/code>ing them.<\/p>\n<p>However, because\u00a0<code>ValueTask<\/code>\u00a0and\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0may wrap reusable objects, there are actually significant constraints on their consumption when compared with\u00a0<code>Task<\/code>\u00a0and\u00a0<code>Task&lt;TResult&gt;<\/code>, should someone veer off the desired path of just\u00a0<code>await<\/code>ing them. In general, the following operations should\u00a0<em>never<\/em>\u00a0be performed on a\u00a0<code>ValueTask<\/code>\u00a0\/\u00a0<code>ValueTask&lt;TResult&gt;<\/code>:<\/p>\n<ul>\n<li><strong>Awaiting a\u00a0<code>ValueTask<\/code>\u00a0\/\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0multiple times.<\/strong>\u00a0The underlying object may have been recycled already and be in use by another operation. In contrast, a\u00a0<code>Task<\/code>\u00a0\/\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0will never transition from a complete to incomplete state, so you can await it as many times as you need to, and will always get the same answer every time.<\/li>\n<li><strong>Awaiting a\u00a0<code>ValueTask<\/code>\u00a0\/\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0concurrently.<\/strong>\u00a0The underlying object expects to work with only a single callback from a single consumer at a time, and attempting to await it concurrently could easily introduce race conditions and subtle program errors. It&#8217;s also just a more specific case of the above bad operation: &#8220;awaiting a\u00a0<code>ValueTask<\/code>\u00a0\/\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0multiple times.&#8221; In contrast,\u00a0<code>Task<\/code>\u00a0\/\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0do support any number of concurrent awaits.<\/li>\n<li><strong>Using\u00a0<code>.GetAwaiter().GetResult()<\/code>\u00a0when the operation hasn&#8217;t yet completed.<\/strong>\u00a0The\u00a0<code>IValueTaskSource<\/code>\u00a0\/\u00a0<code>IValueTaskSource&lt;TResult&gt;<\/code>\u00a0implementation need not support blocking until the operation completes, and likely doesn&#8217;t, so such an operation is inherently a race condition and is unlikely to behave the way the caller intends. In contrast,\u00a0<code>Task<\/code>\u00a0\/\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0do enable this, blocking the caller until the task completes.<\/li>\n<\/ul>\n<p>If you have a\u00a0<code>ValueTask<\/code>\u00a0or a\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0and you need to do one of these things, you should use\u00a0<code>.AsTask()<\/code>\u00a0to get a\u00a0<code>Task<\/code>\u00a0\/\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0and then operate on that resulting task object. After that point, you should never interact with that\u00a0<code>ValueTask<\/code>\u00a0\/\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0again.<\/p>\n<p><strong>The short rule is this:<\/strong>\u00a0with a\u00a0<code>ValueTask<\/code>\u00a0or a\u00a0<code>ValueTask&lt;TResult&gt;<\/code>, you should either\u00a0<code>await<\/code>\u00a0it directly (optionally with\u00a0<code>.ConfigureAwait(false)<\/code>) or call\u00a0<code>AsTask()<\/code>\u00a0on it directly, and then never use it again, e.g.<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true\">\/\/ Given this ValueTask&lt;int&gt;-returning method\u2026\r\npublic ValueTask&lt;int&gt; SomeValueTaskReturningMethodAsync();\r\n\u2026\r\n\/\/ GOOD\r\nint result = await SomeValueTaskReturningMethodAsync();\r\n\r\n\/\/ GOOD\r\nint result = await SomeValueTaskReturningMethodAsync().ConfigureAwait(false);\r\n\r\n\/\/ GOOD\r\nTask&lt;int&gt; t = SomeValueTaskReturningMethodAsync().AsTask();\r\n\r\n\/\/ WARNING\r\nValueTask&lt;int&gt; vt = SomeValueTaskReturningMethodAsync();\r\n... \/\/ storing the instance into a local makes it much more likely it'll be misused,\r\n    \/\/ but it could still be ok\r\n\r\n\/\/ BAD: awaits multiple times\r\nValueTask&lt;int&gt; vt = SomeValueTaskReturningMethodAsync();\r\nint result = await vt;\r\nint result2 = await vt;\r\n\r\n\/\/ BAD: awaits concurrently (and, by definition then, multiple times)\r\nValueTask&lt;int&gt; vt = SomeValueTaskReturningMethodAsync();\r\nTask.Run(async () =&gt; await vt);\r\nTask.Run(async () =&gt; await vt);\r\n\r\n\/\/ BAD: uses GetAwaiter().GetResult() when it's not known to be done\r\nValueTask&lt;int&gt; vt = SomeValueTaskReturningMethodAsync();\r\nint result = vt.GetAwaiter().GetResult();<\/pre>\n<\/div>\n<p>There is one additional advanced pattern that some developers may choose to use, hopefully only after measuring carefully and finding it provides meaningful benefit. Specifically,\u00a0<code>ValueTask<\/code>\u00a0\/\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0do expose some properties that speak to the current state of the operation, for example the\u00a0<code>IsCompleted<\/code>\u00a0property returning\u00a0<code>false<\/code>\u00a0if the operation hasn&#8217;t yet completed, and returning\u00a0<code>true<\/code>\u00a0if it has (meaning it&#8217;s no longer running and may have completed successfully or otherwise), and the\u00a0<code>IsCompletedSuccessfully<\/code>\u00a0property returning\u00a0<code>true<\/code>\u00a0if and only if it&#8217;s completed and completed successfully (meaning attempting to await it or access its result will not result in an exception being thrown). For very hot paths where a developer wants to, for example, avoid some additional costs only necessary on the asynchronous path, these properties can be checked prior to performing one of the operations that essentially invalidates the\u00a0<code>ValueTask<\/code>\u00a0\/\u00a0<code>ValueTask&lt;TResult&gt;<\/code>, e.g.\u00a0<code>await<\/code>,\u00a0<code>.AsTask()<\/code>. For example, in the\u00a0<code>SocketsHttpHandler<\/code>\u00a0implementation in .NET Core 2.1, the code issues a read on a connection, which returns a\u00a0<code>ValueTask&lt;int&gt;<\/code>. If that operation completed synchronously, then we don&#8217;t need to worry about being able to cancel the operation. But if it completes asynchronously, then while it&#8217;s running we want to hook up cancellation such that a cancellation request will tear down the connection. As this is a very hot code path, and as profiling showed it to make a small difference, the code is structured essentially as follows:<\/p>\n<div class=\"highlight highlight-source-cs\">\n<pre class=\"lang:default decode:true \">int bytesRead;\r\n{\r\n    ValueTask&lt;int&gt; readTask = _connection.ReadAsync(buffer);\r\n    if (readTask.IsCompletedSuccessfully)\r\n    {\r\n        bytesRead = readTask.Result;\r\n    }\r\n    else\r\n    {\r\n        using (_connection.RegisterCancellation())\r\n        {\r\n            bytesRead = await readTask;\r\n        }\r\n    }\r\n}<\/pre>\n<\/div>\n<p>This pattern is acceptable, because the\u00a0<code>ValueTask&lt;int&gt;<\/code>\u00a0isn&#8217;t used again after either\u00a0<code>.Result<\/code>\u00a0is accessed or it&#8217;s awaited.<\/p>\n<h2>Should every new asynchronous API return ValueTask \/ ValueTask&lt;TResult&gt;?<\/h2>\n<p>In short, no: the default choice is still\u00a0<code>Task<\/code>\u00a0\/ <code>Task&lt;TResult&gt;<\/code>.<\/p>\n<p>As highlighted above,\u00a0<code>Task<\/code>\u00a0and\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0are easier to use correctly than are\u00a0<code>ValueTask<\/code>\u00a0and\u00a0<code>ValueTask&lt;TResult&gt;<\/code>, and so unless the performance implications outweigh the usability implications,\u00a0<code>Task<\/code>\u00a0\/\u00a0<code>Task&lt;TResult&gt;<\/code>are still preferred. There are also some minor costs associated with returning a\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0instead of a\u00a0<code>Task&lt;TResult&gt;<\/code>, e.g. in microbenchmarks it&#8217;s a bit faster to\u00a0<code>await<\/code>\u00a0a\u00a0<code>Task&lt;TResult&gt;<\/code>\u00a0than it is to\u00a0<code>await<\/code>\u00a0a\u00a0<code>ValueTask&lt;TResult&gt;<\/code>, so if you can use cached tasks (e.g. you&#8217;re API returns\u00a0<code>Task<\/code>\u00a0or\u00a0<code>Task&lt;bool&gt;<\/code>), you might be better off performance-wise sticking with\u00a0<code>Task<\/code>\u00a0and\u00a0<code>Task&lt;bool&gt;<\/code>.\u00a0<code>ValueTask<\/code>\u00a0\/\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0are also multiple words in size, and so when these are\u00a0<code>await<\/code>d and a field for them is stored in a calling async method&#8217;s state machine, they&#8217;ll take up a little more space in that state machine object.<\/p>\n<p>However,\u00a0<code>ValueTask<\/code>\u00a0\/\u00a0<code>ValueTask&lt;TResult&gt;<\/code>\u00a0are great choices when a) you expect consumers of your API to only\u00a0<code>await<\/code>\u00a0them directly, b) allocation-related overhead is important to avoid for your API, and c) either you expect synchronous completion to be a very common case, or you&#8217;re able to effectively pool objects for use with asynchronous completion. When adding abstract, virtual, or interface methods, you also need to consider whether these situations will exist for overrides\/implementations of that method.<\/p>\n<h2>What&#8217;s Next for ValueTask and ValueTask&lt;TResult&gt;?<\/h2>\n<p>For the core .NET libraries, we&#8217;ll continue to see new\u00a0<code>Task<\/code>\u00a0\/\u00a0<code>Task&lt;TResult&gt;<\/code>-returning APIs added, but we&#8217;ll also see new\u00a0<code>ValueTask<\/code> \/ <code>ValueTask&lt;TResult&gt;<\/code>-returning APIs added where appropriate. One key example of the latter is for the new\u00a0<code>IAsyncEnumerator&lt;T&gt;<\/code>\u00a0support planned for .NET Core 3.0.\u00a0<code>IEnumerator&lt;T&gt;<\/code>\u00a0exposes a\u00a0<code>bool<\/code>-returning\u00a0<code>MoveNext<\/code>\u00a0method, and the asynchronous\u00a0<code>IAsyncEnumerator&lt;T&gt;<\/code>\u00a0counterpart exposes a\u00a0<code>MoveNextAsync<\/code>method. When we initially started designing this feature, we thought of\u00a0<code>MoveNextAsync<\/code>\u00a0as returning a\u00a0<code>Task&lt;bool&gt;<\/code>, which could be made very efficient via cached tasks for the common case of\u00a0<code>MoveNextAsync<\/code>\u00a0completing synchronously. However, given how wide-reaching we expect async enumerables to be, and given that they&#8217;re based on interfaces that could end up with many different implementations (some of which may care deeply about performance and allocations), and given that the vast, vast majority of consumption will be through\u00a0<code>await foreach<\/code>\u00a0language support, we switched to having\u00a0<code>MoveNextAsync<\/code>\u00a0return a\u00a0<code>ValueTask&lt;bool&gt;<\/code>. This allows for the synchronous completion case to be fast but also for optimized implementations to use reusable objects to make the asynchronous completion case low-allocation as well. In fact, the C# compiler takes advantage of this when implementing async iterators to make async iterators as allocation-free as possible.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The .NET Framework 4 saw the introduction of the\u00a0System.Threading.Tasks\u00a0namespace, and with it the\u00a0Task\u00a0class. This type and the derived\u00a0Task&lt;TResult&gt;\u00a0have long since become a staple of .NET programming, key aspects of the asynchronous programming model introduced with C# 5 and its\u00a0async\u00a0\/\u00a0await\u00a0keywords. In this post, I&#8217;ll cover the newer\u00a0ValueTask\/ValueTask&lt;TResult&gt;\u00a0types, which were introduced to help improve asynchronous performance in [&hellip;]<\/p>\n","protected":false},"author":360,"featured_media":21759,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[9,43,77,108],"class_list":["post-20679","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","tag-net-core","tag-bcl","tag-fundamentals","tag-performance"],"acf":[],"blog_post_summary":"<p>The .NET Framework 4 saw the introduction of the\u00a0System.Threading.Tasks\u00a0namespace, and with it the\u00a0Task\u00a0class. This type and the derived\u00a0Task&lt;TResult&gt;\u00a0have long since become a staple of .NET programming, key aspects of the asynchronous programming model introduced with C# 5 and its\u00a0async\u00a0\/\u00a0await\u00a0keywords. In this post, I&#8217;ll cover the newer\u00a0ValueTask\/ValueTask&lt;TResult&gt;\u00a0types, which were introduced to help improve asynchronous performance in [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/20679","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=20679"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/20679\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/21759"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=20679"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=20679"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=20679"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}