Я создаю приложение 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");
}
}