Convert a ValueTask<T> to a non generic ValueTask - c#

The question asked here is the same as the one here and is aimed to create a definitive solution to it.
The most accurate answer is by Stephen Toub himself in this issue that is exactly about this question. The "recommendended code" is the following one:
public static ValueTask AsValueTask<T>(this ValueTask<T> valueTask)
{
if (valueTask.IsCompletedSuccessfully)
{
valueTask.GetResult();
return default;
}
return new ValueTask(valueTask.AsTask());
}
This answer is not up-to-date - a ValueTask doesn't expose a GetResult() (only a Result property) - and THE question is:
Do we need to "pull" the Result out of the ValueTask (to "release" the IValueTaskSource that may operate under this ValueTask)?
If yes:
is it the .GetAwaiter() call that is missing above?
OR is a fake call to the property is guaranteed to work var fake = valueTask.Result;? Always? (I'm afraid of dead code elimination.)
If not, is a straight implementation like the following one enough (and optimal)?
public static ValueTask AsNonGenericValueTask<T>( in this ValueTask<T> valueTask )
{
return valueTask.IsCompletedSuccessfully ? default : new ValueTask( valueTask.AsTask() );
}

What's missing in that code is .GetAwaiter():
public static ValueTask AsValueTask<T>(this ValueTask<T> valueTask)
{
if (valueTask.IsCompletedSuccessfully)
{
valueTask.GetAwaiter().GetResult();
return default;
}
return new ValueTask(valueTask.AsTask());
}
You're partially right in that you don't care about the result. But you might care about a thrown exception or cancellation that you'll miss if you don't query the result.
Or you can write it like this:
public static async ValueTask AsValueTask<T>(this ValueTask<T> valueTask)
=> await valueTask;

You can use either:
valueTask.GetAwaiter().GetResult();
...or:
_ = valueTask.Result;
Both of those delegate to the underlying IValueTaskSource<T>.GetResult method, assuming that the ValueTask<T> is backed by a IValueTaskSource<T>. Using the shorter (second) approach should be slightly more efficient, since it involves one less method invocation.
You could also omit getting the result entirely. There is no requirement that a ValueTask<T> must be awaited at least once, or that its result must be retrieved at least once. It is entirely valid to be handed a ValueTask<T> and then forget about it. The documented restriction is:
A ValueTask<TResult> instance may only be awaited once, [...]
It's a "may only", not a "must".
It is still a good idea to get the result though. By retrieving the result you are signaling that the ValueTask<TResult> has been consumed, and so the underlying IValueTaskSource<T> can be reused. Reusing IValueTaskSource<T> instances makes ValueTask<T>-based implementations more efficient, because they allocate memory less frequently. To get an idea, take a look at the internal System.Threading.Channels.AsyncOperation<TResult> class. This class implements the IValueTaskSource<TResult> interface. Here is how the GetResult is implemented:
/// <summary>Gets the result of the operation.</summary>
/// <param name="token">The token that must match <see cref="_currentId"/>.</param>
public TResult GetResult(short token)
{
if (_currentId != token)
{
ThrowIncorrectCurrentIdException();
}
if (!IsCompleted)
{
ThrowIncompleteOperationException();
}
ExceptionDispatchInfo? error = _error;
TResult? result = _result;
_currentId++;
if (_pooled)
{
Volatile.Write(ref _continuation, s_availableSentinel); // only after fetching all needed data
}
error?.Throw();
return result!;
}
Setting the private field Action<object> _continuation to the static readonly value s_availableSentinel allows the AsyncOperation<TResult> to be reused by a subsequent asynchronous operation (like the ChannelReader.ReadAsync for example). Otherwise the next asynchronous operation will allocate a new AsyncOperation<TResult> instance.

Related

Why is Task<T> faster than ValueTask<T>?

I'm doing a benchmark on Task<T> and ValueTask<T>. Source code below:
#LINQPad optimize+ // Enable compiler optimizations
void Main()
{
Util.AutoScrollResults = true;
BenchmarkRunner.Run<TaskAndValueTaskComparsion>();
}
[ShortRunJob]
public class TaskAndValueTaskComparsion
{
[Benchmark]
public ValueTask<int> RunValueTaskWithNew()
{
return new ValueTask<int>(1);
}
[Benchmark]
public Task<int> RunTaskFromResult()
{
return Task.FromResult(1);
}
}
For the result, the Task<T> is way faster than ValueTask<T>. But why? I really expected the ValueTask<T> would cause less allocation when returning task objects.
Thanks for all the commenters. Let's summarize all these valuable info.
There is a TaskCache.cs in the .NET runtime that create cacheable Task for various primitive type's value such as true(bool), false(bool), -1 ~ 9(int). The Task.FromResult leverage these cached Task for it.
So, the benchmark result is incorrect because the Task.FromResult is always return cached version of Task object, and the new ValueTask<int>(1) always returns a new value.
For more information, please read Understanding the Whys, Whats, and Whens of ValueTask.
If you can read Chinese, I also wrote a post yesterday. See here.

Convert Task to Task<T> (Wrap Task with return type of T)

I've read this question but in my case its simpler because I don't have to use Result property. so I was wondering if I can go with simpler approach than what is provided by Stephen Cleary's answer.
Suppose I have this simple interface.
internal interface IBinaryDataReadable
{
Task Load(AsyncDataReader reader);
}
The interface provides method to load object asynchronously. it doesn't return anything since the load result is the object itself.
(The interface is internal and therefor implemented explicitly to avoid exposing implementation.)
Here is how I load binary data.
data = new BinaryData();
await ((IBinaryDataReadable)data).Load(reader);
I want to make this more fluent and verbose so I write this extension method
internal static Task<TData> Load<TData>(this TData data, AsyncDataReader reader)
where TData : IBinaryDataReadable
=> data.Load(reader).ContinueWith(t => data, TaskContinuationOptions.ExecuteSynchronously);
Now loading becomes like this.
data = await new BinaryData().Load(reader);
Is there anything here I should worry about using this method?, for example exception handling etc?
Th same could be done using async/await and foregoes using ContinueWith
internal static async Task<TData> Load<TData>(this TData data, AsyncDataReader reader)
where TData : IBinaryDataReadable {
await data.Load(reader);
return data;
}
That way you can even include exception handling within the method if so desired.
The extension method however does not do much in terms of a fluent interface as the method returns a Task which would need awaiting.
And you would have to call the generic extension explicitly otherwise you are just calling the local member on the type which resolves to void when awaited causing a compile error.
data = await new BinaryData().Load<BinaryData>(reader);
I would advise renaming the extension method to one that would not clash with the existing member on the interface.
data = await new BinaryData().LoadAsync(reader);
I wanted to know if use of ContinueWith introduces problems
I do not see it introducing any problems except for not being able to corral exceptions. But that can be managed by checking for that case and bubbling it up.
internal static Task<TData> LoadAsync<TData>(this TData data, AsyncDataReader reader)
where TData : IBinaryDataReadable {
return data.Load(reader)
.ContinueWith(t => {
var error = t.Exception;
if (error != null && t.IsFaulted)
throw error;
return data;
}, TaskContinuationOptions.ExecuteSynchronously);
}
Though, in my opinion, using async/await was a lot cleaner, easier to read and implement.

Chaining tasks with delays

I have a need to keep track of a task and potentially queue up another task after some delay so the way I'm thinking of doing it looks something like this:
private Task lastTask;
public void DoSomeTask()
{
if (lastTask == null)
{
lastTask = Task.FromResult(false);
}
lastTask = lastTask.ContinueWith(t =>
{
// do some task
}).ContinueWith(t => Task.Delay(250).Wait());
}
My question is, if I do something like this, creating potentially long chains of tasks is will the older tasks be disposed or will they end up sticking around forever because the ContinueWith takes the last task as a parameter (so it's a closure). If so, how can I chain tasks while avoiding this problem?
Is there a better way to do this?
Task.Delay(250).Wait()
You know you're doing something wrong when you use Wait in code you're trying to make asynchronous. That's one wasted thread doing nothing.
The following would be much better:
lastTask = lastTask.ContinueWith(t =>
{
// do some task
}).ContinueWith(t => Task.Delay(250)).Unwrap();
ContinueWith returns a Task<Task>, and the Unwrap call turns that into a Task which will complete when the inner task does.
Now, to answer your question, let's take a look at what the compiler generates:
public void DoSomeTask()
{
if (this.lastTask == null)
this.lastTask = (Task) Task.FromResult<bool>(false);
// ISSUE: method pointer
// ISSUE: method pointer
this.lastTask = this.lastTask
.ContinueWith(
Program.<>c.<>9__2_0
?? (Program.<>c.<>9__2_0 = new Action<Task>((object) Program.<>c.<>9, __methodptr(<DoSomeTask>b__2_0))))
.ContinueWith<Task>(
Program.<>c.<>9__2_1
?? (Program.<>c.<>9__2_1 = new Func<Task, Task>((object) Program.<>c.<>9, __methodptr(<DoSomeTask>b__2_1))))
.Unwrap();
}
[CompilerGenerated]
[Serializable]
private sealed class <>c
{
public static readonly Program.<>c <>9;
public static Action<Task> <>9__2_0;
public static Func<Task, Task> <>9__2_1;
static <>c()
{
Program.<>c.<>9 = new Program.<>c();
}
public <>c()
{
base.\u002Ector();
}
internal void <DoSomeTask>b__2_0(Task t)
{
}
internal Task <DoSomeTask>b__2_1(Task t)
{
return Task.Delay(250);
}
}
This was decompiled with dotPeek in "show me all the guts" mode.
Look at this part:
.ContinueWith<Task>(
Program.<>c.<>9__2_1
?? (Program.<>c.<>9__2_1 = new Func<Task, Task>((object) Program.<>c.<>9, __methodptr(<DoSomeTask>b__2_1))))
The ContinueWith function is given a singleton delegate. So, there's no closing over any variable there.
Now, there's this function:
internal Task <DoSomeTask>b__2_1(Task t)
{
return Task.Delay(250);
}
The t here is a reference to the previous task. Notice something? It's never used. The JIT will mark this local as being unreachable, and the GC will be able to clean it. With optimizations enabled, the JIT will aggressively mark locals that are eligible for collection, even to the point that an instance method can be executing while the instance is being collected by the GC, if said instance method doesn't reference this in the code left to execute.
Now, one last thing, there's the m_parent field in the Task class, which is not good for your scenario. But as long as you're not using TaskCreationOptions.AttachedToParent you should be fine. You could always add the DenyChildAttach flag for extra safety and self-documentation.
Here's the function which deals with that:
internal static Task InternalCurrentIfAttached(TaskCreationOptions creationOptions)
{
return (creationOptions & TaskCreationOptions.AttachedToParent) != 0 ? InternalCurrent : null;
}
So, you should be safe here. If you want to be sure, run a memory profiler on a long chain, and see for yourself.
if I do something like this, creating potentially long chains of tasks is will the older tasks be disposed
Tasks do not require explicit disposal, as they don't contain unmanaged resources.
will they end up sticking around forever because the ContinueWith takes the last task as a parameter (so it's a closure)
It's not a closure. A closure is an anonymous method using a variable from outside the scope of that anonymous method in its body. You're not doing that, so you're not closing over it. Each Task does however have a field where it keeps track of its parent, so the managed Task object will still be accessible if you're using this pattern.
Take a look at the source code of the ContinuationTaskFromTask class. It has the following code:
internal override void InnerInvoke()
{
// Get and null out the antecedent. This is crucial to avoid a memory
// leak with long chains of continuations.
var antecedent = m_antecedent;
Contract.Assert(antecedent != null,
"No antecedent was set for the ContinuationTaskFromTask.");
m_antecedent = null;
m_antecedent is the field that holds a reference to the antecedent ask. The developers here explicitly set it to null (after it is no longer needed) to make sure that there is no memory leak with long chains of continuations, which I guess is your concern.

Where is the return statment for the Task object?

The following code compiles and runs well. But where is the return statement for the Consumer() and Producer() methods?
class Program
{
static BufferBlock<Int32> m_buffer = new BufferBlock<int>(
new DataflowBlockOptions { BoundedCapacity = 10 });
public static async Task Producer() <----- How is a Task object returned?
{
while (true)
{
await m_buffer.SendAsync<Int32>(DateTime.Now.Second);
Thread.Sleep(1000);
}
}
public static async Task Consumer() <----- How is a Task object returned?
{
while (true)
{
Int32 n = await m_buffer.ReceiveAsync<Int32>();
Console.WriteLine(n);
}
}
static void Main(string[] args)
{
Task.WaitAll(Consumer(), Producer());
}
}
While your question states the obvious - the code compiles - and the other answers try to explain-by-example, I think the answer is best described in the following two articles:
"Above-the-surface" answer - full article is here: http://msdn.microsoft.com/en-us/magazine/hh456401.aspx
[...] C# and Visual Basic [...] giving enough hints to the compilers
to build the necessary mechanisms for you behind the scenes. The
solution has two parts: one in the type system, and one in the
language.
The CLR 4 release defined the type Task [...] to represent the
concept of “some work that’s going to produce a result of type T in
the future.” The concept of “work that will complete in the future but
returns no result” is represented by the non-generic Task type.
Precisely how the result of type T is going to be produced in the
future is an implementation detail of a particular task; [...]
The language half of the solution is the new await keyword. A regular
method call means “remember what you’re doing, run this method until
it’s completely finished, and then pick up where you left off, now
knowing the result of the method.” An await expression, in contrast,
means “evaluate this expression to obtain an object representing work
that will in the future produce a result. Sign up the remainder of the
current method as the callback associated with the continuation of
that task. Once the task is produced and the callback is signed up,
immediately return control to my caller.”
2.The under-the-hood explanation is found here: http://msdn.microsoft.com/en-us/magazine/hh456403.aspx
[...] Visual Basic and C# [...] let you express discontinuous
sequential code. [...] When the Visual Basic or C# compiler gets hold
of an asynchronous method, it mangles it quite a bit during
compilation: the discontinuity of the method is not directly supported
by the underlying runtime and must be emulated by the compiler. So
instead of you having to pull the method apart into bits, the compiler
does it for you. [...]
The compiler turns your asynchronous method into a statemachine. The
state machine keeps track of where you are in the execution and what
your local state is. [...]
Asynchronous methods produce Tasks. More specifically, an asynchronous
method returns an instance of one of the types Task or Task from
System.Threading.Tasks, and that instance is automatically generated.
It doesn’t have to be (and can’t be) supplied by the user code. [...]
From the compiler’s point of view, producing Tasks is the easy part.
It relies on a framework-supplied notion of a Task builder, found in
System.Runtime.CompilerServices [...] The builder lets the compiler
obtain a Task, and then lets it complete the Task with a result or an
Exception. [...] Task builders are special helper types meant only for
compiler consumption. [...]
[...] build up a state machine around the production and consumption
of the Tasks. Essentially, all the user logic from the original method
is put into the resumption delegate, but the declarations of locals
are lifted out so they can survive multiple invocations. Furthermore,
a state variable is introduced to track how far things have gotten,
and the user logic in the resumption delegate is wrapped in a big
switch that looks at the state and jumps to a corresponding label. So
whenever resumption is called, it will jump right back to where it
left off the last time.
when the method has no return statement its return type is Task. Have a look at the MSDN page of Async Await
Async methods have three possible return types: Task<TResult>, Task, void
if you need a Task you must specify the return statement. Taken from the MSDN page:
// TASK<T> EXAMPLE
async Task<int> TaskOfT_MethodAsync()
{
// The body of the method is expected to contain an awaited asynchronous
// call.
// Task.FromResult is a placeholder for actual work that returns a string.
var today = await Task.FromResult<string>(DateTime.Now.DayOfWeek.ToString());
// The method then can process the result in some way.
int leisureHours;
if (today.First() == 'S')
leisureHours = 16;
else
leisureHours = 5;
// Because the return statement specifies an operand of type int, the
// method must have a return type of Task<int>.
return leisureHours;
}
async keyword kind of tells compiler that the method body should be used as a Task body. In simple way we can say that these are equivalents to your examples:
public static Task Producer() <----- How is a Task object returned?
{
return Task.Run(() =>
{
while (true)
{
m_buffer.SendAsync<Int32>(DateTime.Now.Second).Wait();
Thread.Sleep(1000);
}
});
}
public static Task Consumer() <----- How is a Task object returned?
{
return Task.Run(() =>
{
while (true)
{
Int32 n = m_buffer.ReceiveAsync<Int32>().Wait();
Console.WriteLine(n);
}
});
}
Of course the compiled result of your methods will be completely different from my examples, because compiler smart enough and it can generate code in such way, so some of the lines in your method will be invoked on the context (thread), which calls the method and some of them on the background context. And this is actually why Thread.Sleep(1000); is not recommended in the body of async methods, because this code can be invoked on the thread, which calls this method. Task has equivalent which can replace Thread.Sleep(1000); the equivalent await Task.Delay(1000), which will be invoked on background thread. As you can see await keyword guaranties you that this call will be invoked on the background context and will not block the caller context.
Let's take a look on one more example:
async Task Test1()
{
int a = 0; // Will be called on the called thread.
int b = await this.GetValueAsync(); // Will be called on background thread
int c = GetC(); // Method execution will come back to the called thread again on this line.
int d = await this.GetValueAsync(); // Going again to background thread
}
So we can say that this will be generated code:
Task Test1()
{
int a = 0; // Will be called on the called thread.
vat syncContext = Task.GetCurrentSynchronizationContext(); // This will help us go back to called thread
return Task.Run(() =>
{
// We already on background task, so we safe here to wait tasks
var bTask = this.GetValueAsync();
bTask.Wait();
int b = bTask.Result;
// syncContext helps us to invoke something on main thread
// because 'int c = 1;' probably was expected to be called on
// the caller thread
var cTask = Task.Run(() => return GetC(), syncContext);
cTask.Wait();
int c = cTask.Result;
// This one was with 'await' - calling without syncContext,
// not on the thread, which calls our method.
var dTask = this.GetValueAsync();
dTask.Wait();
int d = dTask.Result;
});
}
Again, this is not the same code which you will get from compiler, but it should just give you some idea how this works. If you really want to take a look on what will be in the produced library, use for example IlSpy to take a look on generated code.
Also I really recommend to read this article Best Practices in Asynchronous Programming
That's exactly what the async keyword means. It takes a method and (usually) converts it to a Task returning method. If the normal method would have the return type of void, the async method will have Task. If the return type would be some other T, the new return type will be Task<T>.
For example, to download an process some data synchronously, you could write something like:
Foo GetFoo()
{
string s = DownloadFoo();
Foo foo = ParseFoo(s);
return foo;
}
The asynchronous version would then look like this:
Task<Foo> GetFoo()
{
string s = await DownloadFoo();
Foo foo = ParseFoo(s);
return foo;
}
Notice that the return type changed from Foo to Task<Foo>, but you're still returning just Foo. And similarly with void-returning methods: since they don't have to contain a return statement, async Task (without any <T>) methods also don't.
The Task object is constructed by the compiler-generated code, so you don't have to do that.

How to handle return values in async function

When working on data APIs which use async rest calls (I am using RestSharp.Portable), what is the best way to handle return values? Since async function can only return a Task or Task ... but the caller has no way to getting back to the return value ... how would the API return data back to the caller? Global properties?
From what I have read so far, it appears that callback functions are the only way to interact with Response Data?
Take the following method for example; previously I was not using async Rest library and was able to return a value but after converting it to use RestSharp.Portable, I dont see a way to return the value:
public async Task<EntityResourceDescriptor> GetEntityDescriptor(string entityType)
{
TaskCompletionSource<EntityResourceDescriptor> tcs = new TaskCompletionSource<EntityResourceDescriptor>();
var req = new RestRequest("/qcbin/rest/domains/{domain}/projects/{project}/customization/entities/{entityType}");
AddDomainAndProject(req);
req.AddParameter("entityType", entityType, ParameterType.UrlSegment);
client.ExecuteAsync<EntityResourceDescriptor>(req, (res) =>
{
if (res.ResponseStatus == ResponseStatus.Error)
{
tcs.TrySetException(res.ErrorException);
}
else
{
tcs.SetResult(res.Data);
}
}
);
return tcs.Task;
}
Here all I can do is return Task but the caller still has no way to get to the response data or am I missing something obvious? Can the caller subscribe to an event which gets fired at Task.Completed etc.?
I am very fuzzy on this async concept. Are there any examples of writing Portable data APIs?
I think you'll really need to take a step back and read about how to use the async and await keywords. Among other things, you'll need to understand some of the compiler magic that happens behind the scenes when coding async methods.
Here is a good place to start: Asynchronous Programming with Async and Await.
More to your question, the Return Types and Parameters section has this to say:
You specify Task<TResult> as the return type if the method contains a Return (Visual Basic) or return (C#) statement that specifies an operand of type TResult.
It then gives the following code example:
// Signature specifies Task<TResult>
async Task<int> TaskOfTResult_MethodAsync()
{
int hours;
// . . .
// Return statement specifies an integer result.
return hours;
}
Notice how despite the method return type of Task<int>, the return statement simply returns an int, not a Task<int>. That's basically because there is some compiler magic going on that makes this legal only in async methods.
Without wanting to get into all the details, you should also know that the caller of the async method is normally expected to do so using the await keyword, which knows how to deal with the Task or Task<TResult> return values and automatically unwraps the actual expected return value for you in a transparent manner (more compiler magic behind the scenes).
So for the above example, here is one way to call it:
int intValue = await TaskOfTResult_MethodAsync(); // Task<int> is automatically unwrapped to an int by the await keyword when the async method completes.
Or, if you wish to start the async method, perform some other work in the meantime, and then wait for the async method to complete, this can be done like this:
Task<int> t = TaskOfTResult_MethodAsync();
// perform other work here
int intValue = await t; // wait for TaskOfTResult_MethodAsync to complete before continuing.
Hopefully this gives you a general idea of how to pass values back from an async method.
For your specific example, I am not familiar with RestSharp (never used it). But from what little I read, I think you'll want to use client.ExecuteTaskAsync<T>(request) instead of client.ExecuteAsync<T>(request, callback) to better fit in the async-await model.
I'm thinking your method would instead look something like this:
public async Task<EntityResourceDescriptor> GetEntityDescriptor(string entityType)
{
var req = new RestRequest("/qcbin/rest/domains/{domain}/projects/{project}/customization/entities/{entityType}");
AddDomainAndProject(req);
req.AddParameter("entityType", entityType, ParameterType.UrlSegment);
var res = await client.ExecuteTaskAsync<EntityResourceDescriptor>(req);
if (res.ResponseStatus == ResponseStatus.Error)
{
throw new Exception("rethrowing", res.ErrorException);
}
else
{
return res.Data;
}
}
Your calling code would then look like this:
EntityResourceDescriptor erd = await GetEntityDescriptor("entityType");
I hope you manage to get this working. But again, make sure to read the documentation about the async-await style of programming. It's very neat once you wrap your head around the compiler magic that is done for you. But it's so easy to get lost if you don't take the time to really understand how it works.

Categories