Reputation: 55
I make a httpclient call then want to start calculations imediatly. I don't want the calculations disturbed by the returning response. The calculations can take up to 3 seconds.
pseudo-ish code
{
var data = await GetDataFromCloud();
//do calculations - highly time sensitive!
DoCalc() //A recursive job or nested loop *the response is occurring within this call :(
//I want the response to occur here after the work above has completed :)
}
Would lock work here. This code is inside an asynchronous function on the UI thread. DoCalc is made non blocking. The UI thread is not blocked.
Upvotes: 1
Views: 67
Reputation: 30512
This is exactly a scenario where we'd like to want to use async-await!
Async-await is useful when your thread has to wait idly for something else to complete. For example, a file to be read, a database query to be performed, a web-page to be downloaded. Typically scenarios where someone else is doing the work, while your thread is just waiting for the work to complete.
Functions where you can "do something else instead of idly waiting" are declared async. See Stream.ReadAsync
when reading files, Dapper.SQLMapper.QueryAsync
when performing database queries, ToListAsync
and FirstOrDefaultAsync
for database queries in entity-framework, WebClient.DownloadFileAsync
for internet downloads etc.
If you call an async function, the return value is a Task
instead of void
, or a Task<TResult>
instead of TResult
. There is one exception: event handlers don't result a Task but void.
If you want to benefit from async-await you have to define your function async and return a Task
or Task<TResult>
When you call an async function, you may be certain that somewhere in this function is an await. In fact, your compiler will warn you if you forget to await somewhere. Similarly you get a warning if you define your function async but forget to call another async function
After you've called the other async function you can continue working as long as you don't need the results from the call. As soon as you need the results you await the task.
If you start to await the task, and the data is still not available, then your thread will go up its call stack to see if your caller has something to do until your caller's await. Up the call stack again to see if there is work to do, etc.
async Task<MyResult> GetMyData(...)
{
Task<SomeData> taskGetData = GetDataFromCloud(...);
// while the data is being fetched, we can continue working
DoSomethingElse();
// now we need the data:
SomeData fetchedData = await taskGetData;
MyResult result = ProcessFetchedData(fetchedData);
return result;
}
What helped me to understand async-await is this interview with Eric Lippert. Search somewhere in the middle for async-await.
What also helped me was this article by the ever so helpful Stephen Cleary
Upvotes: 0
Reputation: 2470
Assuming that you don't need the data returned form GetDataFromCloud()
to actually perform the calculations, you can grab the Task from the method rather than awaiting it, do your calculations and then await it afterwards.
Something like this:
{
var dataTask = GetDataFromCloud(); // Starts the task and returns it
//do calculations - highly time sensitive!
DoCalc()
var data = await dataTask; // Wait for the task to finish (if it hasn't already)
}
Of course, if the data is required for the calculations then you either need to wait for it all to be downloaded first or handle a "stream" of data by grabbing the HttpResponseMessage and reading the content manually.
EDIT:
It's also worth noting that if something were to go wrong in the request (i.e. an exception is thrown), using this approach you won't know about it until the await
.
Upvotes: 2