异步控制器返回太快了

时间:2017-08-01 09:38:53

标签: c# .net asp.net-web-api model-view-controller async-await

这里的想法是同时运行一些长时间运行的方法,一次运行5个。 当其中15个完成时(3个5个块),我应该从控制器方法返回。

问题在于它太早返回。通常它会在第一个5块之后返回,但我已经看到它从第二个块的中间返回。

^ - 我在所有return语句中都有断点,但这些都没有被击中。我知道它返回,因为我从Javascript调用它并在我的浏览器中有一个断点。返回数据是一个空字符串。在对另一个问题提出建议之后 - 我添加了override void Dispose(..)以查看是否会受到影响,但事实并非如此。 然后我在我的Global.asax.cs中的所有事件中放置了断点,例如在Application_ErrorSession_EndApplication_End中,但是这些事件在过早的回归中不会受到影响无论是。我还在ActionFilterAttribute事件的OnActionExecuted中添加了一个断点,但这并没有被击中!我也安装了elmah,通常会发现错误。我无法找到我的代码返回getJson()来电的位置。

对于块中的每个项目,LongRunning方法每个运行大约需要30秒。 我可以将块数从5增加(或减少)到10,并且在10完成后它仍然会返回。

我尽可能地减少了代码,以清楚地表达问题:

    [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(...);
    }

在我的Javascript断点被点击后,代码继续运行 - 所以我的所有15个进程都完全运行,return Ok(..)的断点被点击。

调用JS是:

$.getJSON('TestAPI/RunTest', { reload: self.reload(), period: self.period() }, function (data) {
    var myData = JSON.parse(data);
    self.myReturnedData(myData);

    createDataTable(myData);
    });

感谢您的帮助。

0 个答案:

没有答案