应用程序关闭时的任务处理

时间:2012-08-25 08:16:24

标签: c# .net multithreading windows-services task-parallel-library

我有一个.Net(v4.0)Windows服务应用程序,它在开始时旋转一个tpl任务,执行某些长时间运行的活动,并且基本上保持应用程序的生命周期,并且因此使用TaskCreationOptions创建。 LongRunning 参数值。

每当服务停止并调用.OnStop()方法时,我 .Cancel()我在创建它时移交给工作任务的CancellationToken(Source)我希望它是 .OnlyOnCanceled(...)继续执行任务。

问题是,服务/流程在没有延续任务的情况下关闭而“完全” - 有时它会相当快地退出,有时会完全耗尽,有时则不会。

这对我来说有意义,因为那个特定的任务可能位于另一个线程而不是主线程上,因此无法“拖延”/阻止主要任务结束。

因为我在那个Windows服务应用程序中没有SynchronizationContext,所以我无法告诉延续任务在主线程上运行/所以我想知道: 我是怎么做的?< / p>

更准确地说,运行tpl任务处理应用程序关闭的最佳实践是什么?

4 个答案:

答案 0 :(得分:3)

您必须等待OnStop方法(或OnPauseOnShutdown)完成您的任务。

OnStop中你需要做大约20秒的时间。如果您认为您的线程不会在20秒内完成,则应致电RequestAdditionalTime。一旦从OnStop返回,您的服务流程就可以终止。

使用ContinueWith异步调用传递给它的委托,无论您是通过ExecuteSynchronously还是使用SynchronizationContext。只要ContinueWith执行,假设它是OnStop的最后一行,OnStop返回并将控制权返回给SCN(好吧,ServiceBase,但它会设置您的服务状态停止并将控制权返回给SCM,可能会终止你的过程。

ExecuteSynchronously表示延续与其继续执行的任务同步运行。即在与任务相同的线程上运行(如果可能)。任务可能在调用ContinueWith的线程上运行(否则无法调用ContinueWith)因此ExecuteSynchronusly并不意味着同步拨打ContinueWith

您需要执行以下操作:

RequestAdditionalTime(TimeSpan.FromSeconds(30).Milliseconds);
cancellationToken.Cancel();
task.Wait();
OnStop

Wait表示在任务完成之前您不会退出OnStop(或者需要超过30秒且您的流程终止)

答案 1 :(得分:1)

这是因为延续任务也以异步方式运行 。要阻止它,您需要指定task continuation option

...
t.ContinueWith(ct => {...}, TaskContinuationOptions.ExecuteSynchronously);

答案 2 :(得分:0)

在延续上指定TaskContinuationOptions.ExecuteSynchronously不会影响前提。如果你等待前面的,然后退出服务,你的继续可能仍然没有运行!

执行此操作的唯一方法是在从OnStop返回之前等待继续任务完成。

答案 3 :(得分:0)

恕我直言,这不适合使用TPL。任务并不是真正意义上的这种“永远运行”。逻辑。

IME,为这项专门的工作开始一个新线程要简单得多。由于默认值为Background = false,因此CLR将在退出之前自动等待它完成(服务规则仍然适用)。

添加私人布尔停止;然后你的线程方法只需要做(while == false){DoStuff(); } DoStoppingStuff();

你的OnStop然后只设置stops = true,你的线程将退出while循环并执行你的停止代码:)

IME你不需要添加volatile,但你当然可以