Сохраните асинхронную задачу, чтобы продолжить выполнение после возвращения результата (ASP.NET) - PullRequest
0 голосов
/ 28 февраля 2019

Я создаю приложение ASP.NET.Приложение отображает результат стороннего WebAPI.Если WebAPI занимает больше 2 секунд, он вернет кэшированный результат.

Приведенный ниже код создает две задачи async, одну для вызова WebAPI и одну для извлечения из кэша.У этого также есть задача таймера.Если веб-задача завершается менее чем за 2 секунды, возвращается ее результат.Если задача таймера завершается первой или веб-задача имеет исключение, возвращается кэшированный результат.Код работает так хорошо.

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);
}

Вопрос : Кроме того, я хочу, чтобы веб-задача продолжала выполняться даже после возврата кэшированного результата вызывающей стороне, чтобы обновленный веб-результат был кэширован ибудет доступен для следующего звонящего.

Я имею в виду создание асинхронного фонового потока с использованием 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");
    }
}
...