Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 处理windows服务错误的正确方法_C#_Multithreading_Windows Services_Threadpool_Semaphore - Fatal编程技术网

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

C# 处理windows服务错误的正确方法,c#,multithreading,windows-services,threadpool,semaphore,C#,Multithreading,Windows Services,Threadpool,Semaphore,我正在构建一个多线程windows服务。一旦所有线程都运行完毕,我就很难找到干净地停止服务的最佳方法。代码如下。我已经看过ManualResetEvent、CountdownEvent和使用Interlocked。我不确定哪一个最适合我的实现 谢谢你的帮助 private bool _isExiting; private bool IsExiting //if this is set to true exit but wait for all threads {

我正在构建一个多线程windows服务。一旦所有线程都运行完毕,我就很难找到干净地停止服务的最佳方法。代码如下。我已经看过ManualResetEvent、CountdownEvent和使用Interlocked。我不确定哪一个最适合我的实现

谢谢你的帮助

    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
        }

    }
private bool正在退出;
private bool isexit//如果设置为true,则退出,但等待所有线程
{
获取{return\u isExiting;}
设置
{
_isExiting=值;
如果(值)
停止();
}
}
私人作业档案器;
启动时受保护的覆盖无效(字符串[]args)
{
尝试
{
探查器=新的探查器(MaxThreads);
ThreadPool.QueueUserWorkItem(DoWork);//主线程为工作设置线程
}
捕获(例外情况除外)
{
对数误差(ex);
停止();
}
}
受保护的空工作(对象数据)
{
而(!IsExit)
{
尝试
{
profiler.RunProfiles(profiles);//这应该等到所有子线程都完成之后
Thread.Sleep(ThreadSleep);//在下一次迭代之前睡眠
}
捕获(例外情况除外)
{
对数误差(ex);
errorCount++;
if(errorCount>10)//如果发生10个严重错误,停止服务
{
IsExiting=true;
打破
}
}
}
}
受保护的覆盖void OnStop()
{
尝试
{
if(探查器!=null)
profiler.IsExiting=true;//在此处设置一个变量以通知所有剩余线程停止
//在这里,它应该等待主线程和子线程完成
base.OnStop();
}
抓住
{
base.OnStop();
}
}
//分析器类
//******************************************************
专用只读信号量_throttle//为允许一次执行的线程数设置限制
公共void运行配置文件(列表配置文件)
{
foreach(配置文件中的var配置文件)
{
if(IsExiting)break;//如果调用退出命令,则停止迭代
_throttle.WaitOne();//等待信号量插槽变为可用
ThreadPool.QueueUserWorkItem(RunProfile,profile);//然后添加到线程队列
}
}
专用void运行配置文件(对象配置文件)
{
尝试
{
var p=(配置文件为配置文件);
if(p==null | | IsExiting)
{
_throttle.Release();//如果找不到配置文件或正在退出,请释放信号量插槽
返回;
}
//****
//做一堆事情
//****
_throttle.Release();//释放信号量插槽
}
捕获(例外情况除外)
{
日志错误(ex);
_throttle.Release();//释放信号量插槽
}
}
如果发生停止事件或某些异常,并且您希望停止服务,我将使用任务(来自.NET 4.0的TPL)并使用CancellationToken来取消任务

但是,如果您想坚持使用信号量或旧的同步原语,那么您的解决方案就可以正常工作

另外,请查看本文:

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