Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it ok to call task.Result in an async method if you know the task is completed?

Tags:

c#

async-await

I understand that calling task.Result in an async method can lead to deadlocks. I have a different twist on the question, though...

I find myself doing this pattern a lot. I have several tasks that return the same types of results, so I can await on them all at once. I want to process the results separately, though:

Task<int> t1 = m1Async();
Task<int> t2 = m2Async();
await Task.WhenAll(t1, t2);

Is it ok to call Result here, since I know the tasks are now completed?

int result1 = t1.Result;
int result2 = t2.Result;

Or, should I use await still...it just seems redundant and can be a bit uglier depending on how I need to process the results:

int result1 = await t1;
int result2 = await t2;

Update: Someone marked my question as a duplicate of this one: Awaiting multiple Tasks with different results. The question is different, which is why I didn't find it in my searches, though one of the detailed answers there does answer may question, also.

like image 348
Cary Avatar asked Oct 21 '16 22:10

Cary


People also ask

What happens when you call async method?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.

What happens if we execute an asynchronous method but do not await it?

If you forget to use await while calling an async function, the function starts executing. This means that await is not required for executing the function. The async function will return a promise, which you can use later.

Is an async method that returns Task?

Async methods can have the following return types: Task, for an async method that performs an operation but returns no value. Task<TResult>, for an async method that returns a value. void , for an event handler.

Which method calls the async Task?

A synchronous method calls an async method, obtaining a Task . The synchronous method does a blocking wait on the Task .


1 Answers

There's nothing inherently wrong or bad about using t1.Result after you've already done an await, but you may be opening yourself up to future issues. What if someone changes the code at the beginning of your method so you can no longer be positive the Tasks have completed successfully? And what if they don't see your code further down that makes this assumption?

Seems to me that it might be better to use the returned value from your first await.

Task<int> t1 = m1Async();
Task<int> t2 = m2Async();
var results = await Task.WhenAll(t1, t2);

int result1 = results[0];
int result2 = results[1];

That way, if someone messes with the first await, there's a natural connection for them to follow to know that your code later is dependent on its result.

You may also want to consider whether Task.WhenAll() is really giving you any value here. Unless you're hoping to tell the difference between one task failing and both failing, it might just be simple to await the tasks individually.

Task<int> t1 = m1Async();
Task<int> t2 = m2Async();

int result1 = await t1;
int result2 = await t2;
like image 87
StriplingWarrior Avatar answered Sep 25 '22 15:09

StriplingWarrior