The idea here is to run some long running methods concurrently, 5 at a time. When 15 of them are done (3 blocks of 5), I should return from the controller method.
The problem is that it returns too early. Usually it returns after the first block of 5, but I've seen it return mid way through the second block.
^ - I have breakpoints at all the return
statements, but these don't get hit. I know it returns because I am calling it from Javascript and have a breakpoint in my browser. The return data is an empty string. Following a suggestion on another question - I added an override void Dispose(..)
to see if this was getting hit, but it wasn't.
Then I put breakpoints in all the events in my Global.asax.cs, such as in Application_Error
, Session_End
and Application_End
, however these don't get hit in the premature return either. I also added a breakpoint in my ActionFilterAttribute
in the OnActionExecuted
event, but this doesn't get hit either! I also have elmah installed which usually catches errors. I cannot find where my code is returning to the getJson()
call.
The LongRunning methods take about 30 seconds each to run, per item in a block. I can increase (or decrease) the block count from 5 to say 10, and it will still return after 10 complete.
I've trimmed down the code as much as possible to give a clear representation of the issue:
[HttpGet]
[Route("TestAPI/RunTest")]
public async Task<IHttpActionResult> RunTest(bool reload, DateTime period)
{
if (reload)
{
await BuildNewDataTest(period);
// Also tried:
// await BuildNewDataTest(period).ContinueWith((x) => { results = _myUoW.GetDataTest(period); });;
}
return Ok(_myUoW.GetDataTest(period));
// return Ok(results);
}
private async Task<bool> BuildNewDataTest(DateTime period)
{
// DoSomeStuff...
DateTime oldDate = DateTime.Now.AddDays(-30);
AddStuffToDatabase();
List<Task> concurrentRuns = new List<Task>();
for (int i = 0; i < 15; i += 5)
{
concurrentRuns.Clear();
List<MyType> block = fullList
.Skip(i)
.Take(5).ToList();
block.ForEach(x => concurrentRuns.Add(RunStuffAsync(period, oldDate, x.IsOpen)));
await Task.WhenAll(concurrentRuns);
}
return true;
}
private async Task<bool> RunStuffAsync(DateTime period, DateTime prevDate, bool isOpen)
{
// DoSomeStuff...
await Task.Run(() =>
{
_myUoW.RunSomeLongRunningProcess(longRunningID, period);
return true;
});
return false;
}
private void AddStuffToDatabase()
{
_myUoW.CreateNewEntry(...);
}
After my Javascript breakpoint is hit, the code continues to run - so all my 15 processes are run fully and my breakpoint at the return Ok(..)
gets hit.
The calling JS is:
$.getJSON('TestAPI/RunTest', { reload: self.reload(), period: self.period() }, function (data) {
var myData = JSON.parse(data);
self.myReturnedData(myData);
createDataTable(myData);
});
Thanks for any help.