返回结果后(ASP.NET),请保持异步任务以继续执行

时间:2019-02-27 21:23:50

标签: c# asp.net asynchronous async-await

我正在构建一个ASP.NET应用程序。该应用程序显示来自第三方WebAPI的结果。如果WebAPI花费2秒钟以上,它将返回缓存的结果。

下面的代码创建两个async任务,一个任务调用WebAPI,另一个任务从缓存中检索。它还有一个计时器任务。如果Web任务在不到2秒的时间内完成,则返回其结果。如果计时器任务首先结束,或者Web任务有异常,则返回缓存的结果。该代码到目前为止运行良好。

public async Task<ActionResult> Index()
{
    Task<string> readFromCacheTask = ReadFromCacheAsync();
    Task<string> readFromWebTask = ReadFromWebAsync();

    try
    {
        Task timerTask = Task.Delay(2000);
        Task completedTask = await Task.WhenAny(readFromWebTask, timerTask);
        await completedTask;
        if (readFromWebTask.Status == TaskStatus.RanToCompletion)
        {
            return Content(readFromWebTask.Result);
        }
    }
    catch (Exception)
    {
        // Return cache result if there is an error getting from web.
    }
    return Content(await readfromCacheTask);
}

问题:我还希望允许Web任务继续运行,即使在将缓存的结果返回给调用者之后也是如此,以便可以将更新的Web结果缓存起来并用于下一个来电者。

我想到的是使用Task.Run中的Application_Start产生一个异步后台线程。该线程包含一个任务集合,并在连续循环中运行。调用控制器时,它将创建一个readFromWebTask并将其添加到后台线程中的任务集合中。

这是一个好方法吗?有没有更好的方法来实现?

澄清@ 2019-02-27 14:46 :readFromWebTask包含用于更新缓存的逻辑。从运行时观察,ASP.NET不允许readFromWebTask运行超过请求完成时间。任务已中止,并且没有运行到最后。在下面的示例中,仅Foo被写入了文本文件。酒吧不在那里。

public class HomeController : Controller
{
    public async Task DelayAndLog()
    {
        string path = @"C:\temp\test.txt";
        System.IO.File.AppendAllText(path, string.Format("{0}: Foo", DateTime.Now));
        await Task.Delay(2000);
        System.IO.File.AppendAllText(path, string.Format("{0}: Bar", DateTime.Now));
    }


    public async Task<ActionResult> Index()
    {
        Task a = DelayAndLog();
        await Task.Delay(1);
        return Content("Hello World");
    }
}

0 个答案:

没有答案