Reputation: 58911
Lets say I have a controller action that cannot be made async (for various reasons), but I have a service that (through several methods) calls a rest service using HttpClient
. Is there any thing to gain by using the async client and using .Wait
or .Result
? Or would it be less performant to use the synchronous method?
So either:
//MyController.cs
public ActionResult GetSomething(int id)
{
//lots of stuff here
var processedResponse = _myService.Get(id);
//lots more stuff here
return new ContentResult(result);
}
//MyService.cs
public ProcessedResponse Get(int id)
{
var client = new HttpClient();
var result = client.Get(_url+id);
return Process(result);
}
Or:
//MyController.cs
public ActionResult GetSomething(int id)
{
//lots of stuff here
var processedResponse = _myService.GetAsync(id).Result;
//or, .Wait, or Task.Run(...), or something similar
//lots more stuff here
return new ContentResult(result);
}
//MyService.cs
public async Task<ProcessedResponse> GetAsync(int id)
{
var client = new HttpClient();
var result = await client.GetAsync(_url+id);
return await Process(result);
}
Upvotes: 2
Views: 2066
Reputation: 2497
It gets interesting when do can do it like this
//MyController.cs
public ActionResult GetSomething(int id)
{
var processedResponseTask = _myService.GetAsyn(id)
//lots of stuff here (1)
var processedResponseTask.Wait();
var processedResponse = processedResponseTask.Result;
//lots more stuff here (2)
return new ContentResult(result);
}
now the lots of stuff here(1) is done in parallel with your async task. (Or if you called your service twice for example). If you don't actually do a lot around lots of stuff here(1) then there isn't much of a point.
Upvotes: 0
Reputation: 46323
In your scenario, no there isn't a good reason, but lets add some functionality:
//MyController.cs
public ActionResult GetSomething(int id)
{
//lots of stuff here
var processedResponse = _myService.GetAsync(id).Result;
//or, .Wait, or Task.Run(...), or something similar
//lots more stuff here
return new ContentResult(result);
}
//MyService.cs
public async Task<ProcessedResponse> GetAsync(int id)
{
var client = new HttpClient();
var pendingResult1 = client.GetAsync(_url+id);
var pendingResult2 = someAsyncOperation();
var result3 = someSyncOperation();
var result1 = await pendingResult;
var result2 = await pendingResult2;
return await Process(result1, result2, result3);
}
Now, since your request takes a while to complete, someAsynchOperation
starts executing immediately instead of waiting for GetAsync()
to complete. someSyncOperation
is also being executed in the meantime.
Without the async
keyword, you would not be able to use await
, so it's better to have it if you plan to have asynchronous execution inside your funciton.
Upvotes: 2
Reputation: 149518
Is there any thing to gain by using the async client and wrapping the method in Task.Run(() => _myService.Get()).Result?
The only thing you'll most likely end up gaining is a deadlock. Think about it, you're queuing a naturally asynchronous method on a thread-pool thread, where the ASP.NET already gave you a thread to process you Action inside. There isn't much sense in that.
If you want to go async, and think you'll actually benefit from the scale provided by asynchrony, then you should re-factor your controllers to be async as well and return a Task<T>
, where you can await
those asynchronous methods.
So I'd either stay synchronous, or re-factor the code top to bottom to support async:
//MyController.cs
public async Task<ActionResult> GetSomethingAsync(int id)
{
//lots of stuff here
await GetAsync(id);
return new ContentResult(result);
}
//MyService.cs
public async Task<ProcessedResponse> GetAsync(int id)
{
var client = new HttpClient();
var result = await client.GetAsync(_url+id);
return await Process(result);
}
Upvotes: 5