3

我正在编写一个接收消息/请求并异步执行它们的 Windows 服务——它不需要等待项目完成,也不需要关心结果。我能够使用 System.Threading.Tasks.Task 成功地将请求作为任务执行。这些项目中的大多数执行速度很快(不到一秒),但有些需要更长的时间(2-3 分钟)。

作为 Windows 服务,我需要响应“停止”命令,并且某些任务仍将运行。最好不要取消任务,因为运行时间较长的任务可能会使数据处于不良状态(并且回滚非常棘手)。

处理这个问题的最佳方法是什么?我想保留一份我已经开始的任务列表,以便我可以执行 WaitAll。在服务执行期间,它将处理数以万计的请求。我怎么知道什么时候从列表中删除已完成的任务,这样列表才不会疯狂增长?我认为我不应该持有对那么多 Task 对象的引用。

提前致谢。

4

2 回答 2

1

您可以CancellationToken用于此目的。一旦发生 OnStop 事件,您只需调用方法Cancel()CancellationTokenSource它将传播到您传递令牌的所有任务。有几种技术可以正确取消任务。如果请求取消,您可以不时在任务中明确检查。或者我相信令牌本身有一个属性 ThrowWhenCancelled,如果已请求取消,令牌将抛出一个CancellationException.

如果您不关心任务结果,但想要有一个跟踪列表,只需将List<Task<T>>(或可能是ConcurrentBag<Task<T>>)保留为局部变量。不时启动另一个任务,该任务将通过列表并检查Task.Status属性,如果它正在运行或其他。

只要您正确维护这些引用,我认为保留这么多引用不应该是一个问题。此外,这取决于您要如何停止应用程序。如果您对与应用程序一起被终止的任务感到满意,您可能根本不会跟踪它们(除非它们持有一些要持有的资源,并且您需要释放它们)。但在大多数情况下,我会说它应该正确完成。

编辑:只需重读您的帖子。RequestAdditionalTimecall 可以帮助您等到长时间运行的任务完成。在 MSDN 上查看:ServiceBase.RequestAdditionalTime 方法

于 2012-08-18T14:26:12.060 回答
1

如果您只关心在服务终止之前完成的任务,我建议您使用Thread而不是Task.

new Thread(WorkerMethod).Start();

以这种方式创建的线程是所谓的前台线程,您的应用程序(服务)在所有前台线程结束之前不会结束。您需要确保所有前台线程在任何情况下都不会挂起,否则您的应用程序将永远不会自行终止。您可以使用相同的方法实现相同的目的,Task但您需要保留已运行的所有任务的列表,并用于Task.WaitAll等待所有任务在您的 Stop 事件中完成。

如果您需要控制您的线程(即保持对它们的引用),您需要使用某种集合。

List<Thread> threads = new List<Thread>();
Thread thrd;
threads.Add(thrd = new Thread(WorkerMethod));
thrd.Start();

但是,如果您确实需要控制和取消您的任务/线程,您应该使用Task它使取消更容易。

于 2012-08-20T12:46:51.283 回答