应用程序关闭时的任务处理 [英] Task Handling on Application Shutdown

查看:93
本文介绍了应用程序关闭时的任务处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

每当服务停止并调用.OnStop()方法时,我 .Cancel() CancellationToken(Source)我在创建它并希望将它移交给worker任务时 .OnlyOnCanceled(...)继续任务要运行.

问题是,服务/进程关闭而没有继续执行任务的整个"操作-有时退出非常快,有时完全运行,有时没有.

这对我来说确实有意义,因为该特定任务可能位于主线程之外的另一线程上,因此无法跟踪"/阻止该主线程结束.

由于我在Windows服务应用程序中没有SynchronizationContext,所以我无法告诉该继续任务在主线程中/在主线程上运行,所以我想知道:我将如何 这样做? /p>

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

解决方案

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

您有大约20秒的时间完成OnStop中需要执行的任何操作.如果您认为线程不会在20秒内完成,则应调用RequestAdditionalTime.从OnStop返回后,您的服务过程便会终止.

使用ContinueWith异步调用传递给它的委托,而不管您是通过ExecuteSynchronously还是使用SynchronizationContext.一旦执行ContinueWith,假定这是OnStop的最后一行,OnStop返回并将控制权返回给SCN(好吧,ServiceBase,但是它将服务的状态设置为STOPPED并将控制权返回给SCM大概终止您的过程.

ExecuteSynchronously表示延续相对于其继续执行的任务是同步运行的.即在与任务相同的线程上运行(如果可能).该任务可能 not 在正在调用ContinueWith的线程上运行(否则它无法调用ContinueWith),因此ExecuteSynchronusly并不意味着对.

您需要执行以下操作:

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

OnStop中,Wait表示您直到任务完成(或者花费30秒以上的时间并且您的进程被终止)后才会从OnStop退出

I have a .Net (v4.0) Windows Service Application that spins of a tpl task at the beginning that performs certain, long running activities and basically stays alive for the application's life time and as such is created with the TaskCreationOptions.LongRunning parameter value.

Whenever the service is stopped and the .OnStop() method is called, I .Cancel() the CancellationToken(Source) I handed over to the worker task when I created it and I want it's .OnlyOnCanceled(...) continuation task to run.

The thing is, the service/process shuts down without that continuation task to run through "entirely" - sometimes it quits rather quickly, sometimes it runs through completely, sometimes it doesn't.

This does make sense to me as that particular task is probably sitting on another thread than the main one and thereby has no way of "stalling"/blocking that main one to end.

As I do not have a SynchronizationContext in that windows service application I can't tell that continuation task to run there/on the main thread so I was wondering: how would I do that?

And more precisely, what's the best practice to handle an application shutdown with running tpl tasks?

解决方案

You'll have to wait for your task to complete in the OnStop method (or OnPause and OnShutdown).

You have about 20 seconds to do whatever you need in OnStop. If you don't think your thread will complete in 20 seconds, you should call RequestAdditionalTime. As soon as you return from OnStop your service process can be terminated.

Using ContinueWith will asynchronously invoke the delegate passed to it, regardless of whether you pass ExecuteSynchronously or use a SynchronizationContext. As soon as the ContinueWith executes, assuming that's the last line of OnStop, OnStop return and returns control to the SCN (well, ServiceBase, but it sets your service's state to STOPPED and returns control to the SCM to presumably terminate your process.

ExecuteSynchronously means that the continuation runs synchronously with regard to the task it's continuing from. i.e. run on the same thread as the task (if possible). The task is likely not running on the thread that is calling ContinueWith (otherwise it couldn't call ContinueWith) so ExecuteSynchronusly doesn't mean synchronously with regard to the call to ContinueWith.

You need to do something like:

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

in OnStop, the Wait means you won't exit from OnStop until your task completes (or it takes longer than 30 seconds and your process gets terminated)

这篇关于应用程序关闭时的任务处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆