The list <MyObject> does not contain a definition for GetAwaiter
I have a method that returns a List <> of an object. This method takes time.
private List<MyObject> GetBigList() { ... slow stuff } This method is called from 4 or 5 sources. So, I thought that I would try to use async and wait for everything to move until this list is created. I added this method:
public async Task<List<MyObject>> GetBigListAsync() { var resultsTask = GetBigList(); var resuls = await resultsTask; return resuls; } But in this line:
var resuls = await resultsTask; I get this error:
List <MyObject> does not contain a definition for GetAwaiter, and the GetAwaiter extension method that takes the first argument of type List <MyObject> cannot be found.
What am I missing?
You seem to be new to asynchronous waiting. What really helped me understand what async-await is doing is the restaurant analogy given by Eric Lippert in this interview. Look somewhere in the middle for asynchronous wait.
Here he describes that if the cook has to wait for something, instead of doing nothing, he starts to look around to see if he can do something else at this time.
Async-await is similar. Instead of waiting to read the file, query the database, load the web page, your stream will go up to the call stack to see if any of the callers are waiting, and execute these operators until it sees the wait. As soon as he sees the wait, the thread goes up the call stack again to see if one of the callers is waiting, etc. After some time, when the file is read or the request is completed, etc., Operators are executed after waiting.
Usually, reading your long list, your topic will be very busy, and will not wait. There is no certainty that ordering another thread to do this job will reduce the time it takes to read your list. Consider measuring both methods.
One reason to use async-await, even if it lengthens the time it takes to read a large list, is to maintain the responsiveness of the caller (user interface?).
To make your function asynchronous, you must do the following:
- Declare the async function;
- Instead of
TResultreturnTask<TResult>and instead ofvoidreturnTask; - If your function calls other asynchronous functions, try to remember the returned task instead of
await, do other useful things that you need to do, andawaittask when you need the result; If you really want to let another thread do busy things. call
Task.Run (() => GetBigList ())
and wait when you need 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 when another thread loads the List (for example, supports a responsive interface), do not do this, or at least measure if you are working faster.
Other articles that helped me understand async-await were - Async await from the very useful Stephen Cleary - and a bit more advanced: Async-Wait best practices .
resultTask is a list returned from GetBigList() , so nothing will happen where it is.
What you can do is unload the task into a separate thread in threadpool using Task.Run and return the expected Task object:
// Bad code public Task<List<MyObject>> GetBigListAsync() { return Task.Run(() => GetBigList()); } While the above example is best suited to what you tried to do, this is not the best practice. Try to make asynchronous GetBigList() by nature or, if it really is not, leave the decision to execute the code in a separate thread to the calling code and do not hide it in the Fe implementation if the calling code already runs async, there is no reason to spawn another thread. This article describes this in more detail.