bobbyalex
bobbyalex

Reputation: 2751

Can I make a method that returns Task<T> to run synchronously?

Consider this rather simple method:

private bool ValidateKey(HttpRequestMessage message)
{

}

The above method is called as follows

if (!ValidateKey(request))
{
//do something
}

Now I want to call a method inside ValidateKey which returns Task. Let's assume it is the ReadAsStringAsync method in HttpRequestMessage:

message.Content.ReadAsStringAsync();

Now since this method can run asynchronously I should ideally call it like this:

string output = await message.Content.ReadAsStringAsync();

But this will require me to change my method signature to include async and the return type to Task and then the caller too... ad infinitum.

It is possible to call ReadAsStringAsync synchronously, i.e, I am willing to have ValidateKey wait till ReadAsStringAsync completes. This will save me the trouble of changing the code just to cater to this one method.

Upvotes: 7

Views: 7162

Answers (3)

i3arnon
i3arnon

Reputation: 116636

No. If the operation is inherently asynchronous you can't run it synchronously. You can however block the thread and wait for it to complete.

I would highly advise against doing that though. You should make your operation async all the way or don't bother using an async operation at all.

You can also use AsyncContext by Stephen Cleary:

string output = AsyncContext.Run(() => message.Content.ReadAsStringAsync());

If you still plan on blocking then use GetAwaiter().GetResult() as it's closer in exception handling to what await would do:

string output = message.Content.ReadAsStringAsync().GetAwaiter().GetResult();

Upvotes: 10

Patrick Hofman
Patrick Hofman

Reputation: 157098

Initial (wrong) answer part (I will leave it here for future reference)

You can use Task.RunSynchronously to make the task run synchronously, while technically it is still asynchronous, but you block the current execution, so it is sort of synchronous:

Task<string> t = message.Content.ReadAsStringAsync();

t.RunSynchronously();

string result = t.Result;

This only works if your method returns a new Task (since you can only call Run once), so this won't work when the method is declared async...

Solution

Just simply wait for the result, in a synchronous way. This will block the execution.

Task<string> t = message.Content.ReadAsStringAsync();

string result = t.Result;

Upvotes: 1

RePierre
RePierre

Reputation: 9576

ReadAsStringAsync() returns a Task<string> so, in order to wait (block) for the result you just need to get the Result property:

var task = message.Content.ReadAsStringAsync();
string output = task.Result;

Upvotes: 1

Related Questions