代码之家  ›  专栏  ›  技术社区  ›  Cristian Vintila

处理windows服务错误的正确方法

  •  0
  • Cristian Vintila  · 技术社区  · 12 年前

    我正在构建一个多线程窗口服务。一旦所有线程都运行完,我就很难找到干净地停止服务的最佳方法。代码如下。我已经看过手动重置事件、倒计时事件和使用联锁。我不确定哪一个最适合我的实现。

    谢谢你的帮助。

        private bool _isExiting;
        private bool IsExiting //if this is set to true exit but wait for all threads
        {
            get { return _isExiting; }
            set
            {
                _isExiting = value;
                if (value)
                    Stop();
            }
        }
       private JobProfiler profiler;
    
       protected override void OnStart(string[] args)
        {
            try
            {
                profiler = new Profiler(MaxThreads);
                ThreadPool.QueueUserWorkItem(DoWork); // main thread set up thread for work
            }
            catch (Exception ex)
            {
                LogError(ex);
                Stop();
            }
        }
    
        protected void DoWork(object data)
        {
            while (!IsExiting)
            {
                try
                {
                    profiler.RunProfiles(profiles); //this should wait until all child threads are done
                    Thread.Sleep(ThreadSleep); //sleep before next iteration
                }
                catch (Exception ex)
                {
                    LogError(ex);
                    errorCount++;
    
                    if (errorCount > 10)  //if 10 serious errors happen stop the service
                    {
                        IsExiting = true;
                        break;
                    }
                }
            }
        }
    
        protected override void OnStop()
        {
            try
            {
    
                if(profiler != null)
                    profiler.IsExiting = true; //setting a variable here to signal all remaining threads to stop
    
                //here it should be waiting for the main and child threads to finish
    
                base.OnStop();
            }
            catch
            {
                base.OnStop();
            }
        }
    
    
        //profiler class
        //******************************************************
    
        private readonly Semaphore _throttle;   //setting up a throttle for the number of threads we will allow to execute at once
    
        public void RunProfiles(List<Profiles> profiles)
        {
            foreach (var profile in profiles)
            {
                if (IsExiting) break; //if an exit command is called stop iterating
    
                _throttle.WaitOne(); // Wait on a semaphore slot to become available
                ThreadPool.QueueUserWorkItem(RunProfile, profile ); //then add to thread queue
    
            }
        }
    
        private void RunProfile(object profile)
        {
            try
            {
                var p = (profile as Profile);
    
                if (p == null || IsExiting)
                {
                    _throttle.Release(); // Release the semaphore slot if profile not found or if we're exiting
                    return;
                }
    
                //****
                //do a bunch of stuff
                //****
    
                _throttle.Release(); // Release the semaphore slot
    
            }
            catch (Exception ex)
            {
                log.Error(ex);
                _throttle.Release(); // Release the semaphore slot
            }
    
        }
    
    1 回复  |  直到 12 年前
        1
  •  0
  •   paulik    12 年前

    我会使用Tasks(.NET 4.0中的TPL),并使用CancellationToken在发生Stop事件或出现某些异常并且您想要停止服务时取消任务。

    但是,如果您想坚持使用信号量或旧的同步原语,那么您的解决方案会很好地工作。

    另请查看本文: Threading

    这里有几个有用的例子,可以帮助您选择最佳解决方案。我相信CountdownEvent是高度优化和独立于操作系统的,所以从你的列表中,我会选择它。