Async/Wait in REST api on IIS Express - c#

I'm building a RESTful web api that is going to fire off several tasks, wait for them to complete then return some data. But I keep having problems with it seeming to hang when waiting. I scaled it down the the most basic:
[Authorize]
public class ValuesController : ApiController
{
public IEnumerable<string> Get([FromUri]bool enableWait)
{
Task t = Silly(enableWait);
t.Wait();
return new string[] { "value1", "value2" };
}
private async Task Silly(bool delay)
{
if (delay)
await Task.Delay(1);
}
}
If I pass false it returns without any issue. If I return true, it should wait for 1 millisecond (plus Task/Asnyc overhead) then return. However it just hangs there.
I'm running this on the IIS Express that comes with VS 2017. Any clues?

When implementing async/await you need to make sure you are implementing it all the way through. Your controller action needs to be async, and it needs to await your Silly() method:
public async Task<IEnumerable<string>> Get()
{
return await Silly();
}
You also have to make sure your Silly() method is calling the proper async methods it needs, making sure you are await-ing them.

Related

Integrating async await into synchronous methods

I've been banging my head against a wall for two days now, and frankly I'm annoyed with myself because I just can't seem to get it.
I'm in a webapi context. During this request I need to send some data to one of our other systems, this system is slow to return, due to heavy calculations and multiple database saves etc etc. I need to log the result of this operation, regardless of whether it is successful or not. But I don't want to wait around for it to finish.
I've read that I should be async await all the way from top to bottom. I would have to convert numerous methods if I decided to do this, as I'm already 3 or 4 methods deep, which I fear would branch out even more.
What are my options here? If I go async await all the way down, what do I do with the methods higher up the stack, like my WebApi controllers?
Here is my code, I've tried to thin it down as much as I can. Right now I'm using Task.Result() in the method PushResult(). Which to my understanding is blocking the async? This code works in that the request gets sent. But the TestLog is always last, not first. Therefore not async.
//I'm in a public service and referenced twice
private void MyEndProcess()
{
// other stuff
_vendorPushService.PushResult(); // This could take a while and I have to wait for it!
_logService.PostLog(LogType.TestLog, "Test");
}
//I'm referenced above and somewhere else in the code base
public void PushResult()
{
ExternalResultModel externalResultModel = _resultService.GetExternalResultModel();
PushedResultModel pushedResult = new PushedResultModel();
try
{
pushedResult = _vendorRequestService.PushResultAsync(externalResultModel).Result;
}
catch (Exception ex)
{
pushedResult.Success = false;
}
if (pushedResult.Success)
{
_logService.PostLog(LogType.SuccessLog, pushedResult.Message);
}
else
{
_logService.PostLog(LogType.FailedLog, pushedResult.Message);
}
}
public async Task<PushedResultModel> PushResultAsync(ExternalResultModel externalResultModel)
{
// setup the requestMessage
HttpResponseMessage responseMessage = await _httpRequestService
.SendRequest(requestMessage)
.ConfigureAwait(false);
return new PushedResultModel
{
Success = responseMessage.IsSuccessStatusCode,
Message = await responseMessage.Content.ReadAsStringAsync()
};
}
public class HttpRequestService : IHttpRequestService
{
private readonly HttpClient _httpClient;
public HttpRequestService(IHttpClientAccessor httpClientAccessor)
{
_httpClient = httpClientAccessor.HttpClient;
}
public async Task<HttpResponseMessage> SendRequest(HttpRequestMessage requestMessage)
{
HttpResponseMessage httpResponseMessage = await _httpClient.SendAsync(requestMessage).ConfigureAwait(false);
return httpResponseMessage;
}
}
You should implement async await all the way from top to bottom.
If I go async await all the way down, what do I do with the methods higher up the stack, like my WebApi controllers?
Just make your controller actions async like this:
[RoutePrefix("api")]
public class PresidentsController : ApiController
{
[Route("presidents")]
public async Task<IHttpActionResult> GetPresidents()
{
await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false);
return Ok();
}
}
It's easiest way to implement async methods. Even if it will add some work to change everything to async it will benefit in future, because You will avoid many problem with async code.
If you absolutly HAVE to use async method in synchronous methods make it block in ONE place, like this:
public void MySyncMethod()
{
try
{
this.MyAsyncMethod().Wait();
}
catch (Exception exception)
{
//omited
}
}
private async Task MyAsyncMethod()
{
await AsyncLogic().ConfigureAwait(false);
}
But i don't recommend it. You should just use async await all the way to controller action.
In your comment you said you want to process a task in the background and not make the client calling your API wait. To do that, you don't really need to use async/await.
Try this:
private void MyEndProcess()
{
// other stuff
Task.Run(_vendorPushService.PushResult()).ConfigureAwait(false); //fire and forget
_logService.PostLog(LogType.TestLog, "Test");
}
The Task.Run will start the task, and the ConfigureAwait(false) tells it that it does not need to resume on the same context that we're currently on (meaning that the context can close before the task is finished - i.e. the response can be sent back without waiting for the task to finish).
You will get a compiler warning that you're not awaiting Task.Run, but that's what you want.
Keep in mind that when you do this, HttpContext.Current will not be available inside PushResult.

async chaining blocks webapi call

I've a flow: WebApi > ServiceFramework > DBLayer > MongoDB.
Since its a new application, I ensured to have async from the ground up in all layers. However, when my DB Layer has async code, webapi never gets a response back.
API CONTROLLER
[HttpGet]
public IHttpActionResult GetAllRecords()
{
var result = FrameworkApi.GetRecords().Result;
return Ok(result);
}
above calls > FRAMEWORK API
public async Task<List<Record>> GetRecords()
{
return await FrameworkDbApi.GetRecords();
}
above calls > DB FRAMEWORK API (which Calls MongoDB)
public async Task<List<Record>> GetRecords()
{
return await Task.Run(() =>
NoSqlDocumentClient.GetDefaultDatabase().Result.
GetCollection<Record>("record").AsQueryable().ToList());
//following Synchronous version works..but defeats the purpose
//return NoSqlDocumentClient.GetDefaultDatabase().Result
// .GetCollection<Record>("record").AsQueryable().ToList();
}
However, when the operations in either DBLayer or Framework are invoked via test case, I do get result. But when invoked via WebApi controller, the asynchronous version never returns a response while synchronous version works fine.
But when invoked via WebApi controller, the asynchronous version never
returns a response while synchronous version works fine.
That's because your actual request is deadlocking. When you invoke the method via WebAPI, which has a SynchronizationContext, you're seeing the deadlock, in contrary to your test which hasn't got one, when the test runs fine. This is the reason why you shouldn't block on async code.
Your call-chain should look like this in order to avoid deadlocking (this is what it means to go "async all the way":
[HttpGet]
public async Task<IHttpActionResult> GetAllRecordsAsync()
{
var result = await FrameworkApi.GetRecordsAsync();
return Ok(result);
}
public Task<List<Record>> GetRecordsAsync()
{
return FrameworkDbApi.GetRecordsAsync();
}
public async Task<List<Record>> GetRecordsAsync()
{
var result = await NoSqlDocumentClient.GetDefaultDatabase();
return result.GetCollection<Record>("record").AsQueryable().ToList();
}

ActionNameAsync-ActionNameCompleted vs async-await in Asp.NET MVC

I'm starting with Async MVC and I would like to know which is the main difference between this two implementations of an AsyncController.
The first one is using the ViewNameAsync and ViewNameCompleted implementation:
public class HomeController : AsyncController
{
// ... Manager declaration ...
public void IndexAsync()
{
AsyncManager.OutstandingOperations.Increment();
Manager.ExpensiveOperationCompleted += () =>
{
Debug.WriteLine("Expensive operation completed.");
AsyncManager.OutstandingOperations.Decrement();
};
Manager.ExpensiveOperationAsync();
}
public ActionResult IndexCompleted()
{
return View();
}
}
And the second one is using async-await implementation:
public class HomeController : Controller
{
// ... Manager declaration ...
public async Task<ActionResult> Index()
{
await Manager.ExpensiveOperation();
return View();
}
}
The "main difference" is that the Async/Completed approach is using an outdated and less maintainable way to do asynchronous request handling.
The main reason you do it this way (await the same line) is to tell the thread resource manager that it can balance the thread with other threads. This will allow other threads with higher priority to finish. You can also reference your expensive operation as a variable and then later down the code block, await it there. This will allow your expensive operation to do it's thing while the rest of the code executes. Basically like using Thread.Join.
Using a completed event isn't going to work in this case, considering your IndexAsync will return before your expensive operation completes and may cause undesired results if a recycle happens.

async await calling into multiple synchronous methods

I'm wondering how to best handle this async await chain where multiple CPU bound methods need to be called sequentially after the async chain.
I've typed up a small example below.
I'm just trying to find out what the best performing / least side effecting pattern is. I want to make sure I'm not defeating the async benefits. My Filter methods do not access anything that is async and awaitable so to make them async means I would have to return Task.Run(() => Filter1(criterion)) in the calling method or something like await Task.Run(() => { return events; }); in the filter methods themselves. Which way to go for a best practice is the question. This is where most discussions stop so a full example and recommendation would be nice.
Are there any 4.5 async await gurus out there who can give good advice?
namespace test
{
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
public class sampleController : ApiController
{
private Service _service;
public sampleController()
{
_service = new Service();
}
public async Task<HttpResponseMessage> SomeTask(DiagnosesSearchCriterion criterion)
{
return Request.CreateResponse<IEnumerable<Diagnosis>>(HttpStatusCode.OK, await _service.GetDiagnosesByGroup(criterion));
}
}
public class Service
{
private Repository _repository;
public Service()
{
_repository = new Repository();
}
public async Task<IEnumerable<Diagnosis>> GetDiagnosis(DiagnosesSearchCriterion criterion)
{
System.IO.Stream events = await _repository.GetEvents(criterion);
// Will these block? Should they be async? They are CPU bound...
// how to best handle this, they need to be called sequentially in most cases.
events = Filter1(criterion, events);
events = Filter2(criterion, events);
return new Diagnosis[]{};
}
public System.IO.Stream Filter1(DiagnosesSearchCriterion criterion, System.IO.Stream events)
{
// CPU bound PLINQ and Parallel filtering logic here.....
return events;
}
public System.IO.Stream Filter2(DiagnosesSearchCriterion criterion, System.IO.Stream events)
{
// CPU bound PLINQ and Parallel filtering logic here.....
// ....
return events;
}
}
public class Repository
{
public async Task<System.IO.Stream> GetEvents(DiagnosesSearchCriterion criterion)
{
WebClient wc = new WebClient();
return await wc.OpenReadTaskAsync("http://www.blah.com/stuff");
}
}
}
On the server side, your primary benefit from async is scalability - that is, the thread pool thread is freed up from handling a request if the request is just waiting for some I/O to complete.
In this case (where your methods are CPU-bound), there's no benefit from making them async. You'll still be taking up a thread pool thread (and adding a small amount of overhead) by using Task.Run. Since they should be executed sequentially, the easiest way to do this is to invoke them synchronously, just like your code is currently doing.
I think this scenario is addressed in the excellent Async in ASP.NET video. Note that this same situation on the client side would be handled differently. On the client side, your primary benefit from async is responsiveness, so it would make sense to toss CPU work into a thread pool thread (Task.Run), since that would free up the UI thread.
(As a side note, it's usually not a good idea to do parallel processing on a server, unless you're sure your user count will be quite low).

ASP.Net MVC 4 controller hangs whenever async is used

I'm using Visual Studio 2012 RC with .Net 4.5 and ASP MVC 4 RC. It hangs whenever I use async at all. The controller action method uses async but is not itself an async controller method.
There are no errors logged or exceptions thrown, but the browser shows "Waiting for www.myweb.local" forever.
// Simplest possible async
public class Waiter
{
public async Task<int> GetValue()
{
await Task.Yield();
return await Task.Factory.StartNew(() => 42);
}
}
// simplest possible controller that uses the async
public class HomeController : Controller
public ActionResult Index()
{
var waiter = new Waiter();
var resultTask = waiter.GetValue();
int result = resultTask.Result;
// it never gets here
return View();
}
}
I have done the things that are noted in this answer, and it still does not work.
ie. The web.config contains
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
And the magic words await Task.Yield(); are in the async method.
The .Net framework version is 4.5.50501. I have observed this behaviour on IIS Express and on IIS 6.0.
I tried applying the "July 2012 update" to VS2012, but that did not fix it.
This answer suggests that it may be because the task is already completed when I wait for it, however if that was the case, this should work and it does not:
public class Waiter
{
public async Task<int> GetValue()
{
await Task.Yield();
return await Task.Factory.StartNew(() =>
{
Thread.Sleep(1500);
return 42;
});
}
}
A couple of people have suggested that ConfigureAwait(false) is needed, but this code does not work either:
public async Task<int> GetValue()
{
var task = new Task<int>(() => 42);
return await task.ConfigureAwait(false);
}
The following does work with the razor view engine, but not with spark. Surely there should be a way to get the other scenario working as well? Can one not use the async Tasks inside synchronous code?
public class Waiter
{
public async Task<int> GetValue()
{
return await Task.Factory.StartNew(() => 42);
}
}
public class HomeController : Controller
{
public async Task<ActionResult> IndexAsync()
{
await Task.Yield();
var waiter = new Waiter();
int result = await waiter.GetValue();
return View();
}
}
I know that is this isn't released software, but Microsoft's RCs are usually quite stable, so I'm surprised that it fails, and fails in an unhelpful way.
You are causing a deadlock, just like this question.
James Manning's suggestion is correct, but you have to await the result of ConfigureAwait, like this:
public async Task<int> GetValue()
{
var task = new Task<int> (() => 42);
return await task.ConfigureAwait(false);
}
In general, mixing synchronous and asynchronous code is a Really Bad Idea unless you Really Know what you're doing. Making the controller action asynchronous would be much better.
I have had async working in the beta just fine. I've not tested it, but I'm guessing it's because your controller method is not async. Change it to this:
public async Task<ActionResult> IndexAsync()
{
var waiter = new Waiter();
int result = await waiter.GetValue();
// it never gets here
return View();
}

Categories