我有一个.net(V4.0)的Windows服务在执行某些,长时间运行的活动一开始就TPL的任务是旋转的应用,基本上保持活着的应用程序的生命周期,因此与TaskCreationOptions创建。 LongRunning参数值。
每当服务被停止,并且.OnStop()方法被调用,我.Cancel()中的CancellationToken(来源)我交给工人任务时,我创造了它,我想它的.OnlyOnCanceled(...)延续任务跑。
问题是,服务/进程关闭而没有后续任务,通过“完全”运行 - 有时它退出相当快,有时它贯穿完全,有时没有。
这有一定道理,以我为特定的任务可能是坐在另一个线程比主之一,因此没有“拖延” /阻断主要的一个结束的方式。
由于我没有在Windows服务应用程序,我不能告诉后续任务在主线程,所以我想知道在那里运行/年的SynchronizationContext:我该怎么做 ?
更确切地说,有什么处理与运行TPL任务的应用程序停机的最佳做法 ?
你必须等待你的任务,在完成OnStop
方法(或OnPause
和OnShutdown
)。
你有20秒左右做任何你需要OnStop
。 如果你不认为你的线程将在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秒,你的进程被终止)
出现这种情况是因为延续任务也异步运行。 为了它阻止你需要指定任务延续选项 :
...
t.ContinueWith(ct => {...}, TaskContinuationOptions.ExecuteSynchronously);
指定TaskContinuationOptions.ExecuteSynchronously
上延续不影响前因。 如果等待的前因,然后退出服务,您的延续可能仍无法运行!
要做到这一点的唯一方法是等待后续任务从返回之前完成OnStop
。
恕我直言,这是一个坏适合使用TPL的。 任务是不是真的意味着这种“永远运行”的逻辑。
IME,这是更简单/更容易启动一个新的线程为这个专门的工作。 由于默认为背景= false时,CLR会自动等待它退出之前完成(服务规则仍然适用)。
添加私人布尔停止; 然后你的线程方法只需要而做的(停止== FALSE){DoStuff(); } DoStoppingStuff(); } DoStoppingStuff();
你调用OnStop那么就设置停止=真,你的线程将退出while循环,做你停止代码:)
IME你不需要添加挥发性,但你肯定能