c# - 在关闭程序之前确认所有任务都已完成
问题描述
在我的程序中,启动了很多任务。此任务可以启动其他任务。但是当程序关闭时(Main 方法结束),所有正在运行的任务都会在它们的工作中停止。
我需要在程序关闭时,关闭进程等待所有任务。为此,我注册了所有已启动的任务,并在最后一条指令中等待所有注册任务:
public static class HostedTask
{
private readonly static ConcurrentQueue<Task> _tasks = new ConcurrentQueue<Task>();
public static void Run(Action action)
{
var task = Task.Factory.StartNew(action, TaskCreationOptions.LongRunning);
_tasks.Enqueue(task);
}
public static void Wait()
{
while (_tasks.Any())
{
if (_tasks.TryDequeue(out Task task))
{
task.Wait();
}
}
}
}
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
for (int i = 0; i < 100; i+= 10)
{
LongBackgroundWork(i);
}
HostedTask.Wait();
}
static void LongBackgroundWork(int id)
{
HostedTask.Run(() =>
{
Console.WriteLine(id + " Begin");
Thread.Sleep(TimeSpan.FromSeconds(10));
Console.WriteLine(id + " End");
for (var i = id + 1; i < id + 10; i++)
ChildWork(i);
});
}
static void ChildWork(int id)
{
HostedTask.Run(() =>
{
Console.WriteLine(id + " Begin");
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine(id + " End");
});
}
这种策略有一些问题:
- 藏品永远不会被清理,它可以无限增长
- 需要替换所有任务声明
- 不管理 ContinueWith
- 不要管理异步/等待
你有其他策略/想法吗?
编辑:使示例复杂化以生成子工作。
解决方案
不确定您到底要做什么,但也许像下面这样的东西更适合您?
它确保每次任务结束时它都会被列表删除(锁定的),并且您可以等待所有任务结束。
public static class HostedTask
{
private readonly static List<Task> _tasks = new List<Task>();
private static Object taskLocker = new object();
public static async Task Run(Action action)
{
var task = Task.Factory.StartNew(action, TaskCreationOptions.LongRunning);
lock (taskLocker)
_tasks.Add(task);
await task;
lock (taskLocker)
_tasks.Remove(task);
}
public static void Wait()
{
IEnumerable<Task> anys;
do
{
lock (taskLocker)
{
anys = _tasks.Where(t => !t.IsCompleted);
}
if ((anys != null) && (anys.Count() > 0))
Task.WhenAll(anys).Wait();
else return;
} while (true);
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
for (int i = 0; i < 100; i++)
{
LongBackgroundWork(i);
}
ShortBackgroundWork(-1);
HostedTask.Wait();
}
static Task LongBackgroundWork(int id)
{
return HostedTask.Run(() =>
{
Console.WriteLine(id + " Begin");
Thread.Sleep(TimeSpan.FromSeconds(10));
Console.WriteLine(id + " End");
});
}
static Task ShortBackgroundWork(int id)
{
return HostedTask.Run(() =>
{
Console.WriteLine(id + " Begin");
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.WriteLine(id + " End");
});
}
}
推荐阅读
- algorithm - 为什么这个 F# 序列表达式是立方时间而不是线性的?
- mysql - A Database Error Occurred 错误编号:1064 WH'at line 14
- c# - 如何使用一行代码为所有 SqlCommand 设置相同的 CommandTimeout?
- ios - 从错误提交的旧提交中删除 Pod 引用
- c# - OpenID Connect 不适用于 ASP.NET MVC 5
- font-awesome - FontAwesome 坏了
- javascript - 使用 gapi 在 google 登录集成中使电话号码共享成为可选
- swiftui - 使用 Xcode 11.3 在 SwiftUI 上的 json
- spring - Spring boot - 多模块项目多个application.properties
- solr - 如何在 solr 服务器中过滤日期时间