I have a method that returns a List<> of an object. This method takes a while to run.
private List<MyObject> GetBigList()
{
... slow stuff
}
This method is called from 4 or 5 sources. So, I thought I would try and use async and await to keep things moving while this list builds. I added this method:
public async Task<List<MyObject>> GetBigListAsync()
{
var resultsTask = GetBigList();
var resuls = await resultsTask;
return resuls;
}
But, on this line:
var resuls = await resultsTask;
I get this error:
List<MyObject> does not contain a definition for GetAwaiter,
and no extension method 'GetAwaiter' accepting a first argument of type List<MyObject> could be found.
What am I missing?
It seems you're a newbee to async-await. What really helped me to understand what async-await does is the restaurant analogy given by Eric Lippert in this interview. Search somewhere in the middle for async await.
Here he describes that if a cook has to wait for something, instead of doing nothing he starts looking around to see if he can do something else in the meantime.
Async-await is similar. Instead of awaiting for a file to be read, a database query to return, a web page to be downloaded, your thread will go up the callstack to see if any of the callers are not awaiting and performs those statements until he sees an await. Once he sees the await the thread goes up the call stack again to see if one of the callers is not awaiting etc. After a while when the file is read, or the query is finished etc, the statements after the await are performed.
Normally while reading your big list your thread would be very busy instead of idly waiting. It's not certain that ordering another thread to do the stuff would improve the time needed to read your list. Consider measuring both methods.
One reason to use async-await, even if it would lengthen the time
needed to read the big list, would be to keep the caller (user
interface?) responsive.
To make your function async, you should do the following:
Declare the function async;
Instead of TResult return Task<TResult> and instead of void return Task;
If your function calls other async functions, consider remembering the returned task instead of await, do other useful stuff you need to do and await the task when you need the result;
If you really want to let another thread do the busy stuff. call
Task.Run( () => GetBigList())
and await when you need the results.
private async Task<List<MyObject>> GetBigListAsync()
{
var myTask = Task.Run( () => GetBigList());
// your thread is free to do other useful stuff right nw
DoOtherUsefulStuff();
// after a while you need the result, await for myTask:
List<MyObject> result = await myTask;
// you can now use the results of loading:
ProcessResult(result);
return result;
}
Once again: if you have nothing useful to do while the other thread is loading the List (like keeping UI responsive), don't do this, or at least measure if you are faster.
Other articles that helped me understanding async-await were
- Async await, by the ever so helpful Stephen Cleary,
- and a bit more advanced: Async-Wait best practices.
resultTask is just the list returned from GetBigList(), so nothing will happen async there.
What you can do is offload the task to a separate thread on the threadpool by using Task.Run and return the awaitable Task object:
// Bad code
public Task<List<MyObject>> GetBigListAsync()
{
return Task.Run(() => GetBigList());
}
While above example best matches what you were trying to do, it is not best practice. Try to make the GetBigList() async by nature or if there really is no way, leave the decision about executing the code on a separate thread to the calling code and don't hide this in the implementation F.e. if the calling code already runs async, there is no reason to spawn yet another thread. This article describes this in more detail.
A couple of years later but I feel it is worth to add for the collection, once people search for the resolution since .NET has changed quite a bit:
return await Task.FromResult(GetBigList())
Related
Are there differences between this two approaches? Or program runs similarly in this two cases? If there are differences could you say what are these differences.
First approach:
Task myTask = MyFunctionAsync();
await myTask;
Second approach:
await MyFunctionAsync();
Short version: "not really, at least not in an interesting way"
Long version: awaitables aren't limited to Task/Task<T>, so it is possible (trivially so, in fact) to create code that compiles fine with:
await MyFunctionAsync();
but doesn't compile with:
Task myTask = MyFunctionAsync();
await myTask;
simply because MyFunctionAsync() returns something that isn't a task. ValueTask<int> would be enough for this, but you can make exotic awaitables if you want. But: if we replace Task with var, i.e.
var myTask = MyFunctionAsync();
await myTask;
then now the only difference is that we can refer to myTask at other points in the code, if we want to. This isn't exactly uncommon; the two main scenarios being
combining multiple checks over concurrent code, perhaps using WhenAny or WhenAll
(usually in the case of ValueTask[<T>]) checking whether the awaitable completed synchronously, to avoid the state machine overhead in the synchronous case
They are effectively the same. The difference is that the first way lets you do more steps before you wait for a response. So you could start many tasks concurrently in the first way, and then await them all together with await Task.WhenAll(myListOfTasks)
For example:
var myTasks = myEmployees.Select(e => ProcessPayrollAsync(e));
await Task.WhenAll(myTasks);
I would use the first way if you need to for concurrency and the second way if its a simple case because its shorter.
In that particular case, the 2 forms of code are executed in a similar way. Homewer, consider this:
public async Task<int> CalculateResult(InputData data) {
// This queues up the work on the threadpool.
var expensiveResultTask = Task.Run(() => DoExpensiveCalculation(data));
// Note that at this point, you can do some other work concurrently,
// as CalculateResult() is still executing!
// Execution of CalculateResult is yielded here!
var result = await expensiveResultTask;
return result;
}
As the comments in the code above point out, between a task is running and the await call you can execute any other concurrent code.
For more information, read this article.
What really helped me to understand async-await was the cook analogy descrived by Eric Lippert in this interview. Search somewhere in the middle for async-await.
Here he describes a cook making breakfast. Once he put on the kettle to boil water for the tea, he doesn't wait idly for the water to cook. Instead he puts the bread in the toaster, tea in the teapot and starts slicing tomatoes: whenever he has to wait for another apparatus or other cook to finish his job, he doesn't wait idly, but starts the next task, until he needs the results for one of tasks previous tasks.
Async await, does the same: whenever another process has to do something, where your thread can do nothing but wait for the other process to finish, the thread can look around to see if it can do other things instead. You typically see async-await when another lengthy process is involved: Writing data to a file, Querying data from a database or from the internet. Whenever your thread has to do this, the thread can order the other process to do something while it continues to do other things:
Task<string> taskReadFile = ReadMyFileAsync(...);
// not awaiting, we can do other things:
DoSomethingElse();
// now we need the result of the file:
string fetchedData = await taskReadFile;
So what happens. ReadMyFileAsync is async, so you know that somewhere deep inside it, the method awaits. In fact, your compiler will warn you if you forget to await.
Once your thread sees the await, it knows that the results of the await are needed, so it can't continue. Instead it goes up the call stack to continue processing (in my example DoSomethingElse()), until it sees an await. It goes up the call stack again and continues processing, etc.
So in fact there is no real difference between your first and your second method. You can compare it with:
double x = Math.Sin(4.0)
versus
double a = 4.0;
double x = Math.Sin(a);
Officially the only difference is that after these statements you can still use a. Similarly you can use information from the task after the await:
Task<MyData> myTask = FetchMyDataAsync(...);
MyData result = await myTask;
// if desired you can investigate myTask
if (result == null)
{
// why is it null, did someone cancel my task?
if (Task.IsCanceled)
{
Yell("Hey, who did cancel my task!");
}
}
But most of the times you are not interested in the task. If you don't have anything else to do while the task is executing, I'd just await for it:
MyData fetchedData = await FetchMyDataAsync(...)
I am going to start by saying that I am learning about mulithreading at the moment so it may be the case that not all I say is correct - please feel free to correct me as required. I do have a reasonable understanding of async and await.
My basic aim is as follows:
I have a body of code that currently takes about 3 seconds. I am trying to load some data at the start of the method that will be used right at the end. My plan is to load the data on a different thread right at the start - allowing the rest of the code to execute independently. Then, at the point that I need the data, the code will wait if the data is not loaded. So far this is all seems to be working fine and as I describe.
My question relates to what happens when I call a method that is async, within a parallel for loop, without awaiting it.
My code follows this structure:
public void MainCaller()
{
List<int> listFromThread = null;
var secondThread = Task.Factory.StartNew(() =>
{
listFromThread = GetAllLists().Result;
});
//Do some other stuff
secondThread.Wait();
//Do not pass this point until this thread has completed
}
public Task<List<int>> GetAllLists()
{
var intList = new List<int>(){ /*Whatever... */};
var returnList = new List<int>();
Parallel.ForEach(intList, intEntry =>
{
var res = MyMethod().Result;
returnList.AddRange(res);
});
return Task.FromResult(returnList);
}
private async Task<List<int>> MyMethod()
{
var myList = await obtainList.ToListAsync();
}
Note the Parallel for Loop calls the async method, but does not await it as it is not async itself.
This is a method that is used elsewhere, so it is valid that it is async. I know one option is to make a copy of this method that is not async, but I am trying to understand what will happen here.
My question is, can I be sure that when I reach secondThread.Wait(); the async part of the execution will be complete. Eg will wait to know wait for the async part to complete, or will async mess up the wait, or will it work seamlessly together?
It seems to me it could be possible that as the call to MyMethod is not awaited, but there is an await within MyMethod, the parallel for loop could continue execution before the awaited call has completed?
Then I think, as it is assigning it by reference, then once the assigning takes place, the value will be the correct result.
This leads me to think that as long as the wait will know to wait for the async to complete, then there is no problem - hence my question.
I guess this relates to my lack of understanding of Tasks?
I hope this is clear?
In your code there is no part that is executed asynchrounously.
In MainCaller, you start a Task and immediately Wait for it to finished.
This is a blocking operation which only introduces the extra overhead of calling
GetAllLists in another Task.
In this Task you call You start a new Task (by calling GettAllLists) but immediately
wait for this Task to finish by waiting for its Result (which is also blocking).
In the Task started by GetAllLists you have the Parallel.Foreach loop which starts
several new Tasks. Each of these 'for' Tasks will start another Task by calling
MyMethod and immediately waiting for its result.
The net result is that your code completely executes synchronously. The only parallelism is introduced in the Parallel.For loop.
Hint: a usefull thread concerning this topic: Using async/await for multiple tasks
Additionally your code contains a serious bug:
Each Task created by the Parallel.For loop will eventually add its partial List to the ReturnList by calling AddRange. 'AddRange' is not thread safe, so you need to have some synchronisation mechanism (e.g. 'Lock') or there is the possibility that your ReturnList gets corrupted or does not contain all the results. See also: Is the List<T>.AddRange() thread safe?
I have three methods where the first result will be used in the next two methods and no data expected to be return back.
result= await DataAccess.Query(param); //Query
await DataAccess.Create(result);
await DataAccess.Update(result);
Do I really need to use await here?
is it correct to use async void
in create and update function?
what will be the right approach to do
a fire and forget here?
if Im not mentioning async will it be fire
and forget?
what is the significance of async without await if it
only used to run synchronously? I can even achieve that without that keyword.
no data expected to be return back.
What about errors? Do you need to return an error code if an error occurs, or is 200 OK acceptable even if the Create or Update fails?
I'm assuming you'll need an error code. 99.99% of calls do.
Do I really need to use await here?
Well, if you want synchronous methods, then you can just call synchronous APIs. I don't know why you would want that, though.
As a reminder: await has nothing to do with returning to the browser. It has everything to do with using fewer thread pool threads, allowing your server to scale further.
is it correct to use async void in create and update function?
No. Never.
what will be the right approach to do a fire and forget here?
The correct approach is "don't". Fire-and-forget is difficult to do correctly, and in fact since you need an error code, you can't do fire-and-forget.
I write more about fire-and-forget - including why StartNew and Task.Run are invalid solutions - on my blog. Note that the only fully reliable solution (including upgrade scenarios) is the last one (distributed architecture).
what is the significance of async without await if it only used to run synchronously? I can even achieve that without that keyword.
It's running serially (in order), not synchronously (blocking a thread). The benefit of async is to allow greater scalability. For more information, see my intro to async on ASP.NET article.
If you need to call several methods in specific order, but this whole set of functions can run asynchronously, I would do:
Task.Run(() =>
{
result = Function();
Create(result);
Update(result);
});
This will separate group of functions into new thread. Since you are not awaiting this task, it is fire and forget.
If your functions are defined as async, you can wait for them to finish like this:
Task.Run(() =>
{
var task = Function();
task.Wait();
var result = task.Result;
Create(result).Wait();
Update(result).Wait();
});
But when you are not going to benefit from async methods, it will be better to override your methods to run synchronously and use the first code
I am just new to this world of asynchronous stuff.
Please bear with my lack of knowledge.
It is said when a method encounters await ... "It tells the awaitable to run the remainder of the method when it completes, and then returns from the async method."
I did not get this part.
So does it mean the method still keeps on running synchronously and waits till the awaitable returns and then proceeds with the rest of the method?
If not please explain then why Task.Run is needed to run a method in the background or in a fire and forget manner. I could still be achieved via await also right? i.e.
The method keeps on executing the rest of the statements without waiting for the await to return.
I hope that is similar to a background run approach. Or is not it? I am confused.
If a method is marked with async and await and that in turn calls another method asynchronously in a separate layer that's also marked with async and await ..
then how the the call of the first method that's marked with async and await from a separate method say name ABC should look like?
I do not want to annotate that method to be async/await. So
Task.Run(() => DoWork());
from ABC () is fine without marking it async/await?
Or is it against the principle of asynchrony?
Here is what I am trying to achieve ...
public IList<CreateCaseOutput> ABC(CreateCaseInput CreateCaseInput,SaveCaseSearchInput SaveCaseSearchInput)
{
CaseSQL.getABCParameters(CreateCaseInput, RequestType, out strSPQuery, out listParam);
var AcctLst = rep.ExecuteStoredProcedure<CreateCaseOutput>(strSPQuery, listParam).ToList();
if (!string.IsNullOrEmpty(AcctLst.ElementAt(0).o_case_seq.ToString()))
{
Task.Run(async () =>
{
await DEF(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
}).ConfigureAwait(false);
}
console.writeLine("After Async called");
return AcctLst;
}
public async Task<SaveCaseSearchOutput>> DEF(SaveCaseSearchInput SaveCaseSearchInput,Int64? case_key)
{
CaseSQL.getDEFParameters(SaveCaseSearchInput, case_key, out strSPQuery, out listParam);
var AcctLst = await rep.ExecuteStoredProcedureAsync<SaveCaseSearchOutput>(strSPQuery, listParam);
return AcctLst;
}
DEF which is async/await needs to be called in the background in fire and forget approach from ABC and once fired I want to continue with rest of ABC and run DEF in the background. What's wrong in this fire and forget approach ? If I call
only
DEF(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
instead of
Task.Run(async () =>
{
await DEF(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
}).ConfigureAwait(false);
}
return AcctLst;
then this code runs synchronously in debugger.
Am I doing something wrong ?
So does it mean the method still keeps on running synchronously and waits till the awaitable returns and then proceeds with the rest of the method?
No. The awaitable has a "callback" mechanism. So, the method just registers itself with the awaitable. When the awaitable completes, it will execute its callbacks, which include the continuation of the async method.
In the meantime, the async method returns an incomplete task.
If not please explain then why Task.Run is needed to run a method in the background or in a fire and forget manner.
If you want to run on a background thread, then use Task.Run. Task.Run just schedules work to the thread pool.
I could still be achieved via await also right? i.e.
The method keeps on executing the rest of the statements without waiting for the await to return.
I hope that is similar to a background run approach. Or is not it? I am confused.
Well, you could "forget" the task by just not awaiting it:
MyMethod()
{
SomeMethodAsync(); // Note: no await; we just ignore the task.
}
You almost never want to do "fire and forget", though. Easily >90% of the time people ask for it, it's actually a design error.
I do not want to annotate that method to be async/await... Or is it against the principle of asynchrony?
That's against the principle. If you think about it, it doesn't really make sense to block on asynchronous code. You want to go through the trouble of making a method asynchronous (meaning it doesn't block a thread), and then block a thread on it? Why, exactly? Sometimes in practice, the code will temporarily end up in this kind of state during a transition to asynchronous code, but it's a tricky place to be.
For more information, see my article on async best practices, particularly "async all the way".
'It is said when a method encounters await ... "It tells the awaitable to run the remainder of the method when it completes, and then returns from the async method."'
So let's say you have a method A that calls a method B. Method B has the "async" keyword in its declaration. In method B there is a time-consuming call to LongMethod, which ultimately returns a string.
What we want here is for method A to not have to wait for ages for method B's LongMethod to complete. So we write in Method B:
string newVariable = await Task.Run(()=>LongMethod());
If LongMethod itself is also async, then LongMethod can only return a void, a non generic Task or a generic Task. Therefore we would have to change the return type in the LongMethod declaration to Task<string>
So back to our story, the LongMethod task has started... At this point method A resumes from the next line of code after the call to method B, and method B continues to wait for the LongMethod to finish, so there are now two threads running. Eventually, the LongMethod completes and method B runs to the end, meanwhile method A has continued to run, or has maybe even finished running.
I hope this gives you a picture of the relationship between Async/Await and Tasks.
Now for question 2:
I think your question is basically asking if Method A in my example needs to be marked "async" because it makes a call to a method marked "async", and no it does not. Also please note that ABC() just needs to have
DoWork()
Not
Task.Run(() => DoWork());
ABC will then stop running until the DoWork method arrives at an 'await' statement.
If DoWork just needs to be run as its own task, and you don't want ABC() to stop at all, then just do
Task.Run(() => DoWork());
There is no benefit marking DoWork as async in this case, because there is no point having any await statements in DoWork.
I hope this helps, sorry if I've misinterpreted your questions!
From what you said in your comment (I'll assume you need the result in ABC)
You just need to write
Task<SaveCaseSearchOutput> t = Task.Run(() =>DEF(SaveCaseSearchInput,AcctLst.ElementAt(0).o_case_seq));
in ABC, instead of the current Task.Run call.
Then at the line in ABC when you require the result write
t.Wait();
SaveCaseSearchOutput g = t.Result;
DEF must remain async but you can remove the await statement in DEF.
So I was asking this question about async , and I thought that it it's just a sugar syntax for :
Task<..>...ContinueWith...
And finally inspect the Result property.
I even asked a question about it here and I was told :
But Today I was corrected by Jon Skeet
" It's a very long way from that".
So what are the core differences between those 2 approaches ?
It is adding a continuation - but manually constructing that continuation can be very painful, due to the need to carry around all the information about where we'd got to and what the local state is.
As a very simple example, I suggest you try to come up with the equivalent of this async method:
public static async Task<int> SumTwoOperationsAsync()
{
var firstTask = GetOperationOneAsync();
var secondTask = GetOperationTwoAsync();
return await firstTask + await secondTask;
}
// These are just examples - you don't need to translate them.
private async Task<int> GetOperationOneAsync()
{
await Task.Delay(500); // Just to simulate an operation taking time
return 10;
}
private async Task<int> GetOperationTwoAsync()
{
await Task.Delay(100); // Just to simulate an operation taking time
return 5;
}
Really try to come up with the equivalent of the first method. I think you'll find it takes quite a lot of code - especially if you actually want to get back to an appropriate thread each time. (Imagine code in that async method also modified a WPF UI, for example.) Oh, and make sure that if either of the tasks fails, your returned task fails too. (The async method will actually "miss" the failure of the second task if the first task also fails, but that's a relatively minor problem IMO.)
Next, work out how you'd need to change your code if you needed the equivalent of try/finally in the async method. Again, that'll make the non-async method more complicated. It can all be done, but it's a pain in the neck.
So yes, it's "just" syntactic sugar. So is foreach. So is a for loop (or any other kind of loop). In the case of async/await, it's syntactic sugar which can do really rather a lot to transform your code.
There are lots of videos and blog posts around async, and I would expect that just watching/reading a few of them would give you enough insight to appreciate that this is far from a minor tweak: it radically changes how practical it is to write large amounts of asynchronous code correctly.
Additionally, being pattern-based, async/await doesn't only work on Task / Task<T>. You can await anything which adheres to the awaitable pattern. In practice very few developers will need to implement the pattern themselves, but it allows for methods like Task.Yield which returns a YieldAwaitable rather than a task.