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:
Put some bread in the toaster.
While the bread is toasting I could be doing other work, but instead, stare at the toaster doing nothing else until it is done.
Get the toast from the toaster, and start a new to-do list.
The new to-do list is: Obtain the piece of toast that I am now holding.
Execute that to-do list. While I'm waiting for the to-do list to complete, go do other work, but the to-do list is always already complete because the job is to obtain a result that I have already obtained. So don't do other work. Just check that yes, I am in fact holding the piece of toast I just wrote a to-do list about.
Now I have a piece of toast.
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:
It is an "asynchronous" workflow where every possible asynchronous advantage has been removed.
The first step -- waiting for the toaster to pop -- has been synchronously waited.
The second step -- asynchronously wait for a task that has already completed -- is never asynchronous!
Never never never write asynchronous code this way.
The right workflow for making a piece of toast is:
Put the bread in the toaster and start it toasting.
Do other work until the toast pops.
Fetch the toast.
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 awaited 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(...);
Related
I have an I/O-bound task implemented with an async-await function.
At some point in this function, I receive some information which allows me to start a concurrent task, which is also I/O-bound (and so it is also implemented with an async-await function). My original task is not bound by this new task - I just need to set it going in the background.
If I do the following, I get warned that I'm not awaiting the call. I don't want to await the call! I want it to happen in the background!
async Task AnotherAsyncThing()
{
// ...
}
async Task SomeAsyncThing()
{
// ...
// run concurrently - warning raised here
Task.Run(async () => await AnotherAsyncThing());
// ...
}
Am I missing something horribly obvious here? It feels like I am!
You can do something like this:
_ = AnotherAsyncThing()
This is the discards feature added in C# 7.0 and is a way of communicating the fact you're not interested in the return value to the compiler.
Yes and no :)
so often bugs occur when people forget to wait for tasks and it is considered a risk in APIs for instance to keep spinning up non awaited tasks because you can sometimes do so rapidly with bad performing client code and if that can steal many resources ... we'll i'm sure You can imagine.
But to signify that You know what You're doing and assume full responsibility, You can use the TPL like this and get rid of the warnings
_ = Task.Run(
() => _ = AnotherAsyncThing()
);
But each time this code is passed it will continue immediately and start something which will also continue to run. So Say your API gets a post, which accidentally happens every 10th millisecond instead of every 10th second as intended ... there is a danger in making the use of these things a standard.
It is a tool for a specific purpose, not the new white for walls, but yea You may have missed that we now should tell by using the nevermind underscore, that we know what we're doing this time and the compiler should back out from helping.
I've recently been learning asynchronous programming and I think I've mastered it. Asynchronous programming is simple just allowing our program to multitask.
The confusion comes with await and async of programming, it seemed to confused me a little more, could somebody help answer some of my concerns?
I don't see the async keyword as much, just something you chuck on a method to let Visual Studio know that the method may await something and for you to allow it to warn you. If it has some other special meaning that actually affects something, could someone explain?
Moving onto await, after talking to a friend I was told I had 1 major thing wrong, await doesn't block the current method, it simply executes the code left in that method and does the asynchronous operation in its own time.
Now, I'm not sure how often this happenes, but lets say yo have some code like this.
Console.WriteLine("Started checking a players data.");
var player = await GetPlayerAsync();
foreach (var uPlayer in Players.Values) {
uPlayer.SendMessage("Checking another players data");
}
if (player.Username == "SomeUsername") {
ExecuteSomeOperation();
}
Console.WriteLine("Finished checking a players data.");
As you can see, I run some asynchronous code on GetPlayerAsync, what happens if we get deeper into the scope and we need to access player, but it hasn't returned the player yet?
If it doesn't block the method, how does it know that player isn't null, does it do some magic and wait for us if we got to that situation, or do we just forbid ourselves from writing methods this way and handle it ourselves.
I've recently been learning asynchronous programming and I think I've mastered it.
I was one of the designers of the feature and I don't feel like I've even come close to mastering it, and you are asking beginner level questions and have some very, very wrong ideas, so there's some hubris going on here I suspect.
Asynchronous programming is simply just allowing our program to multitask.
Suppose you asked "why are some substances hard and some soft?" and I answered "substances are made of arrangements of atoms, and some atom arrangements are hard and some are soft". Though that is undoubtedly true, I hope you would push back on this unhelpful non-explanation.
Similarly, you've just replaced the vague word "asynchronous" with another vague word "multitask". This is an explanation that explains nothing, since you haven't clearly defined what it means to multitask.
Asynchronous workflows are undoubtedly about executing multiple tasks. That's why the fundamental unit of work in a workflow is the Task<T> monad. An asynchronous workflow is the composition of multiple tasks by constructing a graph of dependency relationships among them. But that says nothing about how that workflow is actually realized in software. This is a complex and deep subject.
I don't see the async keyword as much, just something you chuck on a method to let Visual Studio know that the method may await something and for you to allow it to warn you.
That's basically correct, though don't think of it as telling Visual Studio; VS doesn't care. It's the C# compiler that you're telling.
If it has some other special meaning that actually affects something, could someone explain?
It just makes await a keyword inside the method, and puts restrictions on the return type, and changes the meaning of return to "signal that the task associated with this invocation is complete", and a few other housekeeping details.
await doesn't block the current method
Of course it does. Why would you suppose that it does not?
It doesn't block the thread, but it surely blocks the method.
it simply executes the code left in that method and does the asynchronous operation in its own time.
ABSOLUTELY NOT. This is completely backwards. await does the opposite of that. Await means if the task is not complete then return to your caller, and sign up the remainder of this method as the continuation of the task.
As you can see, I run some asynchronous code on GetPlayerAsync, what happens if we get deeper into the scope and we need to access player, but it hasn't returned the player yet?
That doesn't ever happen.
If the value assigned to player is not available when the await executes then the await returns, and the remainder of the method is resumed when the value is available (or when the task completes exceptionally.)
Remember, await mean asynchronously wait, that's why we called it "await". An await is a point in an asynchronous workflow where the workflow cannot proceed until the awaited task is complete. That is the opposite of how you are describing await.
Again, remember what an asynchronous workflow is: it is a collection of tasks where those tasks have dependencies upon each other. We express that one task has a dependency upon the completion of another task by placing an await at the point of the dependency.
Let's look at your workflow in more detail:
var player = await GetPlayerAsync();
foreach (var uPlayer in Players.Values) ...
if (player.Username == "SomeUsername") ...
The await means "the remainder of this workflow cannot continue until the player is obtained". Is that actually correct? If you want the foreach to not execute until the player is fetched, then this is correct. But the foreach doesn't depend on the player, so we could rewrite this like this:
Task<Player> playerTask = GetPlayerAsync();
foreach (var uPlayer in Players.Values) ...
Player player = await playerTask;
if (player.Username == "SomeUsername") ...
See, we have moved the point of dependency to later in the workflow. We start the "get a player" task, then we do the foreach, and then we check to see if the player is available right before we need it.
If you have the belief that await somehow "takes a call and makes it asynchronous", this should dispel that belief. await takes a task and returns if it is not complete. If it is complete, then it extracts the value of that task and continues. The "get a player" operation is already asynchronous, await does not make it so.
If it doesn't block the method, how does it know that player isn't null
It does block the method, or more accurately, it suspends the method.
The method suspends and does not resume until the task is complete and the value is extracted.
It doesn't block the thread. It returns, so that the caller can keep on doing work in a different workflow. When the task is complete, the continuation will be scheduled onto the current context and the method will resume.
await doesn't block the current method
Correct.
it simply executes the code left in that method and does the asynchronous operation in its own time.
No, not at all. It schedules the rest of the method to run when the asynchronous operation has finished. It does not run the rest of the method immediately. It's not allowed to run any of the rest of the code in the method until the awaited operation is complete. It just doesn't block the current thread in the process, the current thread is returned back to the caller, and can go off to do whatever it wants to do. The rest of the method will be scheduled by the synchronization context (or the thread pool, if none exists) when the asynchronous operation finishes.
I had 1 major thing wrong, await doesn't block the current method, it simply executes the code left in that method and does the asynchronous operation in its own time.
But it does block the method, in the sense that a method that calls await won't continue until the results are in. It just doesn't block the thread that the method is running on.
... and we need to access player, but it hasn't returned the player yet?
That simply won't happen.
async/await is ideal for doing all kinds of I/O (file, network, database, UI) without wasting a lot of threads. Threads are expensive.
But as a programmer you can write (and think) as if it were all happening synchronously.
In this code, you will not use Await because GetPlayerAsync() runs some asynchronous code. You can consider it from the perspective that Async and Await are different in that "Async" is waiting while "Await" operates asynchronously.
Try to use Task< T > as return data.
In c# when you invoke the await method inside an async method, the code will be executed from the calling context to that method. What if I want to make an asynchronous call which will just continue from the same line of code directly (even if the asynchronous action did not finish yet) instead of getting back to the calling context? How can I do that?
What if I want to make an asynchronous call which will just continue from the same line of code directly (even if the asynchronous action did not finish yet) instead of getting back to the calling context? How can I do that?
The easiest way, which works whether Something is synchronous or asynchronous:
var _ = Task.Run(() => Something());
But, as Eric Lippert stated:
it is a strange thing to get a task and then not care about what happens when it completes.
Or, as I like to put it: fire-and-forget is almost never what you really want. To "forget" means:
You don't care when it completes.
You don't care whether it completes. E.g., if your app exits (or app pool is recycled if on ASP.NET), then your background work is just lost.
You don't care whether it completes successfully. E.g., if your work throws an exception, you want to silently swallow that exception.
In real-world code, this scenario is extremely rare.
An await is, by definition, a point at which you must asynchronously wait for the task to finish before continuing the workflow. If you don't have to wait, then don't wait! There is no requirement that you await anything.
Your question is rather like asking "I have an IEnumerable<int> but I don't care what integers are in it; do I have to foreach over it?" No, you don't. If you don't care what the result is, you don't have to get a result from a sequence. If you don't care what the result of a task is, you don't have to await it.
But it is a strange thing to get a sequence and then not enumerate it, and it is a strange thing to get a task and then not care about what happens when it completes.
If you want to start the async method and continue inside the function you can do something like Task<string> getStringTask = asyncMethodThatReturnsString();. Then continue until you want to wait for the async task to finish at which point you would call string output = await getStringTask;.
After reading lot of stuff about async/await, I still not sure where do I use await operator in my async method:
public async Task<IActionResult> DailySchedule(int professionalId, DateTime date)
{
var professional = professionalServices.Find(professionalId);
var appointments = scheduleService.SearchForAppointments(date, professional);
appointments = scheduleService.SomeCalculation(appointments);
return PartialView(appointments);
}
Should I create an async version for all 3 method and call like this?
var professional = await professionalServices.FindAsync(professionalId);
var appointments = await scheduleService.SearchForAppointmentsAsync(date, professional);
appointments = await scheduleService.SomeCalculationAsync(appointments);
or Should I make async only the first one ?
var professional = await professionalServices.FindAsync(professionalId);
var appointments = scheduleService.SearchForAppointments(date, professional);
appointments = scheduleService.SomeCalculation(appointments);
What´s is the difference?
I still not sure where do I use await operator in my async method
You're approaching the problem from the wrong end.
The first thing to change when converting to async is the lowest-level API calls. There are some operations that are naturally asynchronous - specifically, I/O operations. Other operations are naturally synchronous - e.g., CPU code.
Based on the names "Find", "SearchForAppointments, and "SomeCalculation", I'd suspect that Find and SearchForAppointments are I/O-based, possibly hitting a database, while SomeCalculation is just doing some CPU calculation.
But don't change Find to FindAsync just yet. That's still going the wrong way. The right way is to start at the lowest API, so whatever I/O that Find eventually does. For example, if this is an EF query, then use the EF6 asynchronous methods within Find. Then Find should become FindAsync, which should drive DailySchedule to be DailyScheduleAsync, which causes its callers to become async, etc. That's the way that async should grow.
As VSG24 has said, you should await each and every call that can be awaited that is because this will help you keep the main thread free from any long running task — that are for instance, tasks that download data from internet, tasks that save the data to the disk using I/O etc. The problem was that whenever you had to do a long running task, it always froze the UI. To overcome this, asynchronous pattern was used and thus this async/await allows you create a function that does the long running task on the background and your main thread keeps talking to the users.
I still not sure where do I use await operator in my async method
The intuition is that every function ending with Async can be awaited (provided their signature also matches, the following) and that they return either a Task, or Task<T>. Then they can be awaited using a function that returns void — you cannot await void. So the functions where there will be a bit longer to respond, you should apply await there. My own opinion is that a function that might take more than 1 second should be awaited — because that is a 1 second on your device, maybe your client has to wait for 5 seconds, or worse 10 seconds. They are just going to close the application and walk away saying, It doesn't work!.
Ok, if one of these is very very fast, it does not need to be async, right ?
Fast in what manner? Don't forget that your clients may not have very very fast machines and they are definitely going to suffer from the frozen applications. So them a favor and always await the functions.
What´s is the difference?
The difference is that in the last code sample, only the first call will be awaited and the others will execute synchronously. Visual Studio will also explain this part to you by providing green squiggly lines under the code that you can see by hovering over it. That is why, you should await every async call where possible.
Tip: If the process in the function is required, such as loading all of the data before starting the application then you should avoid async/await pattern and instead use the synchronous approach to download the data and perform other tasks. So it entirely depends on what you are doing instead of what the document says. :-)
Every async method call needs to be awaited, so that every method call releases the thread and thus not causing a block. Therefore in your case this is how you should do it:
var professional = await professionalServices.FindAsync(professionalId);
var appointments = await scheduleService.SearchForAppointmentsasync(date, professional);
appointments = await scheduleService.SomeCalculationAsync(appointments);
I don't see the different between C#'s (and VB's) new async features, and .NET 4.0's Task Parallel Library. Take, for example, Eric Lippert's code from here:
async void ArchiveDocuments(List<Url> urls) {
Task archive = null;
for(int i = 0; i < urls.Count; ++i) {
var document = await FetchAsync(urls[i]);
if (archive != null)
await archive;
archive = ArchiveAsync(document);
}
}
It seems that the await keyword is serving two different purposes. The first occurrence (FetchAsync) seems to mean, "If this value is used later in the method and its task isn't finished, wait until it completes before continuing." The second instance (archive) seems to mean, "If this task is not yet finished, wait right now until it completes." If I'm wrong, please correct me.
Couldn't it just as easily be written like this?
void ArchiveDocuments(List<Url> urls) {
for(int i = 0; i < urls.Count; ++i) {
var document = FetchAsync(urls[i]); // removed await
if (archive != null)
archive.Wait(); // changed to .Wait()
archive = ArchiveAsync(document.Result); // added .Result
}
}
I've replaced the first await with a Task.Result where the value is actually needed, and the second await with Task.Wait(), where the wait is actually occurring. The functionality is (1) already implemented, and (2) much closer semantically to what is actually happening in the code.
I do realize that an async method is rewritten as a state machine, similar to iterators, but I also don't see what benefits that brings. Any code that requires another thread to operate (such as downloading) will still require another thread, and any code that doesn't (such as reading from a file) could still utilize the TPL to work with only a single thread.
I'm obviously missing something huge here; can anybody help me understand this a little better?
I think the misunderstanding arises here:
It seems that the await keyword is serving two different purposes. The first occurrence (FetchAsync) seems to mean, "If this value is used later in the method and its task isn't finished, wait until it completes before continuing." The second instance (archive) seems to mean, "If this task is not yet finished, wait right now until it completes." If I'm wrong, please correct me.
This is actually completely incorrect. Both of these have the same meaning.
In your first case:
var document = await FetchAsync(urls[i]);
What happens here, is that the runtime says "Start calling FetchAsync, then return the current execution point to the thread calling this method." There is no "waiting" here - instead, execution returns to the calling synchronization context, and things keep churning. At some point in the future, FetchAsync's Task will complete, and at that point, this code will resume on the calling thread's synchronization context, and the next statement (assigning the document variable) will occur.
Execution will then continue until the second await call - at which time, the same thing will happen - if the Task<T> (archive) isn't complete, execution will be released to the calling context - otherwise, the archive will be set.
In the second case, things are very different - here, you're explicitly blocking, which means that the calling synchronization context will never get a chance to execute any code until your entire method completes. Granted, there is still asynchrony, but the asynchrony is completely contained within this block of code - no code outside of this pasted code will happen on this thread until all of your code completes.
Anders boiled it down to a very succinct answer in the Channel 9 Live interview he did. I highly recommend it
The new Async and await keywords allow you to orchestrate concurrency in your applications. They don't actually introduce any concurrency in to your application.
TPL and more specifically Task is one way you can use to actually perform operations concurrently. The new async and await keyword allow you to compose these concurrent operations in a "synchronous" or "linear" fashion.
So you can still write a linear flow of control in your programs while the actual computing may or may not happen concurrently. When computation does happen concurrently, await and async allow you to compose these operations.
There is a huge difference:
Wait() blocks, await does not block. If you run the async version of ArchiveDocuments() on your GUI thread, the GUI will stay responsive while the fetching and archiving operations are running.
If you use the TPL version with Wait(), your GUI will be blocked.
Note that async manages to do this without introducing any threads - at the point of the await, control is simply returned to the message loop. Once the task being waited for has completed, the remainder of the method (continuation) is enqueued on the message loop and the GUI thread will continue running ArchiveDocuments where it left off.
The ability to turn the program flow of control into a state machine is what makes these new keywords intresting. Think of it as yielding control, rather than values.
Check out this Channel 9 video of Anders talking about the new feature.
The problem here is that the signature of ArchiveDocuments is misleading. It has an explicit return of void but really the return is Task. To me void implies synchronous as there is no way to "wait" for it to finish. Consider the alternate signature of the function.
async Task ArchiveDocuments(List<Url> urls) {
...
}
To me when it's written this way the difference is much more obvious. The ArchiveDocuments function is not one that completes synchronously but will finish later.
The await keyword does not introduce concurrency. It is like the yield keyword, it tells the compiler to restructure your code into lambda controlled by a state machine.
To see what await code would look like without 'await' see this excellent link: http://blogs.msdn.com/b/windowsappdev/archive/2012/04/24/diving-deep-with-winrt-and-await.aspx
The call to FetchAsync() will still block until it completes (unless a statement within calls await?) The key is that control is returned to the caller (because the ArchiveDocuments method itself is declared as async). So the caller can happily continue processing UI logic, respond to events, etc.
When FetchAsync() completes, it interrupts the caller to finish the loop. It hits ArchiveAsync() and blocks, but ArchiveAsync() probably just creates a new task, starts it, and returns the task. This allows the second loop to begin, while the task is processing.
The second loop hits FetchAsync() and blocks, returning control to the caller. When FetchAsync() completes, it again interrupts the caller to continue processing. It then hits await archive, which returns control to the caller until the Task created in loop 1 completes. Once that task is complete, the caller is again interrupted, and the second loop calls ArchiveAsync(), which gets a started task and begins loop 3, repeat ad nauseum.
The key is returning control to the caller while the heavy lifters are executing.