I am new to C# async programming and need to see if which of the following is a preferred way to deal with Task object.
I have a class that does this:
var value = this.SomeFunction(...);
var innerValue = await Task.FromResult(value.Result);
Somefunction
looks like below.
protected async Task<JObject> Somefunction(..)
{
..
returns JBoject
..
}
This works fine as expected. Now, I have a suggestion that I shouldn't be using Task.FromResult
with async
functions.
Instead, I should be using something like:
var innerValue = await value; //..this works fine too
But I am not really sure why the 1st one isn't a good practice to get the same thing done. Any leads would be helpful. Thanks
Let's go through what you're doing and say precisely why it is wrong.
var value = this.SomeFunction(...);
First off: use var
when the type is either clear or unimportant. The type is not clear here and it is important.
Second: Name functions that are asynchronous with an Async
suffix.
Let's fix up your example. It's still wrong, but now it is more clear:
Task<Toast> toastTask = this.StartToasterAsync();
Toast toast = await Task.FromResult(toastTask.Result);
This workflow is completely wrong. Let's translate it into English. Here's my to-do list for today:
This workflow is an insane way to make toast. It works -- you end up with a piece of toast at the end -- but no sensible person would do this, and you should not write the equivalent computer program:
Never never never write asynchronous code this way.
The right workflow for making a piece of toast is:
And as we'd expect, the correct way to write your program is much simpler:
Task<Toast> toastTask = this.StartToasterAsync(...);
Toast toast = await toastTask;
Or even better:
Toast toast = await this.StartToasterAsync(...);
You're new to this and you have not internalized the meanings of the various operations on asynchronous workflows. The operations in your little program are:
.Result
means stop being asynchronous and do nothing until the result is available. Note that this can cause deadlocks. You are stopping a thread until the result is available; what if you are stopping the thread that was going to produce the result in the future? Imagine for instance that we did a to-do list of "(1) Order a box of chocolates from the internet. (2) Do nothing until the chocolates arrive. (3) Get the chocolates out of the mailbox." That workflow does not complete because there is a synchronous wait for a result that requires you to do work in the future.await
means this workflow cannot continue until the result is available so asynchronously wait for it. Go off and find other work to do, and when the result is available, we'll start again here.Note that both of them mean the same thing, in that both are points in a workflow where the workflow does not proceed until the result is available. But they are completely different in that Result
is a synchronous wait, and await
is an asynchronous wait. Make sure you understand this. It is the most fundamental point that you must understand.
And finally
FromResult
means someone needs a task, but I already have the result of that task, so make a task that is already complete. When it is await
ed or when Result
is called on it, either way, it returns the result immediately.It is unusual to call FromResult
. If you are in an asynchronous workflow, normally you would just return result;
to signal that a task was complete.
The problem in the first version is not the use of Task.FromResult
, which, from the documentation:
Creates a
Task<TResult>
that's completed successfully with the specified result
The problem is the call value.Result
which performs a synchronous wait. So, you are essentially asynchronously waiting for a synchronous result.
Notice that the first version is a bad wrapper (because of the code that must be generated for the await
call) around this:
var value = this.SomeFunction(...);
var innerValue = value.Result;
To sum up, just use this:
var innerValue = await value;
Or, if there's no code to run between value
and innerValue
, you can ignore the assignment of value
altogether
var innerValue = await this.SomeFunction(...);
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