停止多线程Windows服务

时间:2012-05-17 21:54:02

标签: c# multithreading windows-services threadpool

我在.Net 3.5中有一个多线程Windows服务,当创建多个线程时,我遇到了一些正确停止服务的麻烦。

此服务用于创建一个线程来完成所有工作,我只是将其更改为多线程。它工作正常,但是当服务停止时,如果正在执行多个线程,它将挂起服务直到所有线程都完成。

当服务启动时,我创建一个后台线程来处理主进程:

    protected override void OnStart(string[] args)
    {
        try
        {
            //Global variable that is checked by threads to learn if service was stopped
            DeliveryConstant.StopService = false;
            bool SetMaxThreadsResult = ThreadPool.SetMaxThreads(10, 10);

            ThreadStart st = new ThreadStart(StartThreadPool);
            workerThread = new Thread(st);
            workerThread.IsBackground = true;
            serviceStarted = true;
            workerThread.Start();
        }
        catch (Exception ex)
        {
            //Log something;
        }

这是StartThreadPool方法:

    //Tried with and without this attribute with no success...
    [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]
    public void StartThreadPool()
    {
        while (serviceStarted)
        {
            ProcessInfo input = new ProcessInfo();

            try
            {
                int? NumPendingRequests = GetItems(50, (Guid?)input.ProcessID);

                if (NumPendingRequests > 0)
                {
                    input.ProcessType = 1;
                    input.ProcessID = Guid.NewGuid();
                    ThreadPool.QueueUserWorkItem(new WaitCallback(new DispatchManager().ProcessRequestList), input);
                 }
            }
            catch (Exception ex)
            {
                //Some Logging here
            }
        }

        DeliveryConstant.StopService = true;
    }

我在一个单独的类中创建了一个静态变量,以通知线程服务已停止。当此变量的值为true时,所有线程都应该停止主循环(每个循环的a):

        public static bool StopService;

最后,OnStop方法:

protected override void OnStop()
    {
        DeliveryConstant.StopService = true;

        //flag to tell the worker process to stop
        serviceStarted = false;

        workerThread.Join(TimeSpan.FromSeconds(30));
    }

在ProcessRequestList方法中,在每个foreach的末尾,我检查StopService变量的值。如果是,我打破了循环。

问题在于: 线程是以50个项目的块创建的。当我在数据库中有50个或更少的项目时,只创建一个线程,一切都很好。 当我有超过50个项目时,将创建多个线程,当我尝试停止服务时,它不会停止,直到所有后台线程都完成。

从日志中我可以看到OnStop方法只在所有线程完成后执行。

有什么线索可以改变以解决这个问题吗?

2 个答案:

答案 0 :(得分:9)

这个blog answer表示在所有ThreadPool任务完成之前不会调用OnStop,这对我来说是个新闻,但可以解释你的问题。

我已经部署了许多多线程Windows服务,但我更喜欢创建自己的后台线程而不是使用ThreadPool,因为这些是长时间运行的线程。我实例化工作类并在线程上启动它们的DoWork()方法。我也更喜欢使用回调来启动类来检查停止信号并传递状态,而不是仅仅针对全局变量进行测试。

答案 1 :(得分:3)

您在访问StopService时遇到了内存障碍,如果您有多个CPU,这可能会出现问题。最好锁定任何引用对象,以便对共享变量进行ALL访问。例如:

object @lock;

...

lock (@lock)
{
    StopService = true;
}

编辑:正如另一个答案所揭示的那样,这个问题不是锁定问题,但我在这里留下这个答案作为检查多线程同步方案的事情。

将共享变量设置为volatile在许多情况下也会起作用,但证明它是正确的更复杂,因为它不会发出完整的栅栏。