我正在使用 ASP.NET Core 开发 Web API。我现在的任务是在应用程序关闭时等待所有请求运行完成。所以我认为我需要以某种方式阻止主线程,直到所有任务完成。
我创建了类来包含 Controller 创建的所有任务:
public static class GlobalTasks
{
public static readonly Dictionary<int, Task> TaskDic;
static GlobalTasks()
{
TaskDic = new Dictionary<int, Task>();
}
public static void WaitAll()
{
if (TaskDic.Any())
{
List<Task> taskList = new List<Task>();
foreach (var item in TaskDic)
{
taskList.Add(item.Value);
}
Task.WaitAll(taskList.ToArray());
}
}
public static void Remove(int taskId)
{
TaskDic.Remove(taskId);
}
public static void Add(Task t)
{
TaskDic.Add(t.Id, t);
}
}
然后我只需在 Startup.cs
的 Configure
方法中使用 IHostApplicationLifetime
来在应用程序停止时等待所有任务。
lifetime.ApplicationStopped.Register(() => GlobalTasks.WaitAll());
但据我所知,这不会导致我关闭应用程序时等待我的任务
有什么建议/建议吗?
这就是我将任务添加到字典的方式
[HttpPost]
public async Task<StatusCodeResult> Post([FromBody] Update update)
{
if (!isStoping)
{
GlobalTasks.Add(Task.Factory.StartNew(async () =>
{
await _updateService.EchoAsync(update);
Thread.Sleep(20000);
GlobalTasks.TaskDic.Remove(Task.CurrentId.Value);
}));
return Ok();
}
else
return StatusCode(500);
}
最佳答案
宿主只会给你5 sec在残酷地中止一切之前完成所有任务。您有两种选择来增加它:
UseShutdownTimeout()
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseShutdownTimeout(TimeSpan.FromSeconds(60)); });
添加configuration key到appsettings.config
“ShutdownTimeoutSeconds”:60
但是。您应该使用 BackgroundService执行您的任务,而不是管理静态字典和阻塞线程。您可以实现Producer-Consumer pattern其中 Producer
是您的 Controller ,Consumer
是 BackgroundService
。 Asp.Net Core 将等待所有 BackgroundService
完成工作(但不超过 ShutdownTimeoutSeconds
)并正常关闭。
关于c# - 如何等到所有请求都完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64944645/