C# 线程池/WaitHandle资源泄漏/崩溃

C# 线程池/WaitHandle资源泄漏/崩溃,c#,crash,memory-leaks,threadpool,waithandle,C#,Crash,Memory Leaks,Threadpool,Waithandle,我想我可能需要重新考虑我的设计。我很难缩小一个导致我的电脑完全挂起的bug,有时会抛出VS2010的HRESULT 0x8007000E 我有一个控制台应用程序(稍后我会将其转换为服务),它处理基于数据库队列的文件传输 我正在限制允许传输的线程。这是因为我们正在连接的某些系统只能包含来自特定帐户的特定数量的连接 例如,系统A只能同时接受3个连接(这意味着3个单独的线程)。这些线程中的每一个都有自己独特的连接对象,因此我们不应该遇到任何同步问题,因为它们不共享连接 我们希望按周期处理来自这些系统的

我想我可能需要重新考虑我的设计。我很难缩小一个导致我的电脑完全挂起的bug,有时会抛出VS2010的HRESULT 0x8007000E

我有一个控制台应用程序(稍后我会将其转换为服务),它处理基于数据库队列的文件传输

我正在限制允许传输的线程。这是因为我们正在连接的某些系统只能包含来自特定帐户的特定数量的连接

例如,系统A只能同时接受3个连接(这意味着3个单独的线程)。这些线程中的每一个都有自己独特的连接对象,因此我们不应该遇到任何同步问题,因为它们不共享连接

我们希望按周期处理来自这些系统的文件。例如,我们将允许3个连接,每个连接最多可以传输100个文件。这意味着,要从系统A中移动1000个文件,我们每个周期只能处理300个文件,因为允许3个线程,每个线程处理100个文件。因此,在这个传输的生命周期内,我们将有10个线程。我们一次只能跑3次。因此,将有3个周期,最后一个周期将只使用1个线程来传输最后100个文件。(3个线程x 100个文件=每个周期300个文件)

当前的架构示例如下:

  • System.Threading.Timer通过调用GetScheduledTask()每隔5秒检查一次队列
  • 如果没有什么要做的,GetScheduledTask()就什么也不做
  • 如果有工作,创建一个线程池线程来处理该工作[work thread a]
  • 工作线程A看到有1000个文件要传输
  • 工作线程A看到它只能有3个线程运行到它从中获取文件的系统
  • 工作线程A启动三个新的工作线程[B、C、D]并进行传输
  • 工作线程A等待B、C、D
    [WaitHandle.WaitAll(transfersArray)]
  • 工作线程A看到队列中还有更多的文件(现在应该是700个)
  • 工作线程A创建一个新数组等待
    [transfersArray=new TransferArray[3]
    ,这是系统A的最大值,但可能因系统而异
  • 工作线程A启动三个新的工作线程[B、C、D]并等待它们
    [WaitHandle.WaitAll(transfersArray)]
  • 该过程将重复,直到没有更多文件可移动为止
  • 工作线程A表示它已完成
  • 我正在使用ManualResetEvent处理信号

    我的问题是:

  • 是否有任何明显的情况会导致我遇到的资源泄漏或问题
  • 我是否应该在每次
    WaitHandle.WaitAll(array)
    之后循环遍历数组并调用
    array[index].Dispose()?
  • 此进程的任务管理器下的句柄计数缓慢上升
  • 我正在从System.Threading.Timer调用工作线程A的初始创建。这会有任何问题吗?该计时器的代码是:
  • (一些用于调度的类代码)

    private ManualResetEvent\u ResetEvent;
    私有void Start()
    {
    _IsAlive=真;
    ManualResetEvent transferResetEvent=新的ManualResetEvent(错误);
    //将计划程序计时器设置为5秒间隔
    _ScheduledTasks=新定时器(新定时器回调(ScheduledTasks_Tick),transferResetEvent,2005000);
    }
    私有void ScheduledTasks_Tick(对象状态)
    {
    ManualResetEvent resetEvent=null;
    尝试
    {
    resetEvent=(ManualResetEvent)状态;
    //阻止计时器,直到GetScheduledTasks()完成
    _ScheduledTasks.Change(Timeout.Infinite,Timeout.Infinite);
    GetScheduledTasks();
    }
    最后
    {
    _计划任务变更(50005000);
    WriteLine(“{0}[Main]GetScheduledTasks()已完成”,DateTime.Now.ToString(“MMddyy HH:mm:ss:fff”);
    resetEvent.Set();
    }
    }
    私有void GetScheduledTask()
    {
    尝试
    { 
    //检查数据库连接是否仍处于打开状态
    如果(!\u是活的)
    {
    //处理
    _ConnectionLostNotification=true;
    返回;
    }
    //从数据库中获取预定记录
    IsSchedulerTask任务=null;
    使用(DataTable dt=FastSql.ExecuteDataTable(
    _ConnectionString,“为安全而隐藏”,System.Data.CommandType.StoredProcess,
    new List(){new FastSqlParam(ParameterDirection.Input,SqlDbType.VarChar,“@ProcessMachineName”,Environment.MachineName)})//调用静态类
    {
    如果(dt!=null)
    {
    如果(dt.Rows.Count==1)
    {//只允许一行
    数据行dr=dt.行[0];
    //获取任务信息
    TransferParam.TaskType TaskType=(TransferParam.TaskType)Enum.Parse(typeof(TransferParam.TaskType),dr[“TaskTypeId”].ToString());
    task=ScheduledTaskFactory.CreateScheduledTask(taskType);
    task.Description=dr[“Description”].ToString();
    task.IsEnabled=(bool)dr[“IsEnabled”];
    task.IsProcessing=(bool)dr[“IsProcessing”];
    task.ismanuallunch=(bool)dr[“ismanuallunch”];
    task.ProcessMachineName=dr[“ProcessMachineName”].ToString();
    task.NextRun=(DateTime)dr[“NextRun”];
    task.PostProcessNotification=(bool)dr[“NotifyPostProcess”];
    task.PreProcessNotification=(bool)dr[“NotifyPreProcess”];
    task.Priority=(TransferParam.Priority)Enum.Parse(typeof(TransferParam.SystemType),dr[“PriorityId”].ToString());
    task.sleepments=(int)dr[“sleepments”];
    task.ScheduleId=(int)dr[“ScheduleId”];
    task.CurrentRuns=(int)dr[“CurrentRuns”];
    
    private ManualResetEvent _ResetEvent;
    
    private void Start()
    {
        _IsAlive = true;
        ManualResetEvent transferResetEvent = new ManualResetEvent(false);
        //Set the scheduler timer to 5 second intervals
        _ScheduledTasks = new Timer(new TimerCallback(ScheduledTasks_Tick), transferResetEvent, 200, 5000);
    }
    
    private void ScheduledTasks_Tick(object state)
    {
        ManualResetEvent resetEvent = null;
        try
        {
            resetEvent = (ManualResetEvent)state;
            //Block timer until GetScheduledTasks() finishes
            _ScheduledTasks.Change(Timeout.Infinite, Timeout.Infinite);
            GetScheduledTasks();
        }
        finally
        {
            _ScheduledTasks.Change(5000, 5000);
            Console.WriteLine("{0} [Main] GetScheduledTasks() finished", DateTime.Now.ToString("MMddyy HH:mm:ss:fff"));
            resetEvent.Set();
        }
    }
    
    
    private void GetScheduledTask()
    {
        try 
        { 
            //Check to see if the database connection is still up
            if (!_IsAlive)
            {
                //Handle
                _ConnectionLostNotification = true;
                return;
            }
    
            //Get scheduled records from the database
            ISchedulerTask task = null;
    
            using (DataTable dt = FastSql.ExecuteDataTable(
                    _ConnectionString, "hidden for security", System.Data.CommandType.StoredProcedure,
                    new List<FastSqlParam>() { new FastSqlParam(ParameterDirection.Input, SqlDbType.VarChar, "@ProcessMachineName", Environment.MachineName) })) //call to static class
            {
                if (dt != null)
                {
                    if (dt.Rows.Count == 1)
                    {  //Only 1 row is allowed
                        DataRow dr = dt.Rows[0];
    
                        //Get task information
                        TransferParam.TaskType taskType = (TransferParam.TaskType)Enum.Parse(typeof(TransferParam.TaskType), dr["TaskTypeId"].ToString());
                        task = ScheduledTaskFactory.CreateScheduledTask(taskType);
    
                        task.Description = dr["Description"].ToString();
                        task.IsEnabled = (bool)dr["IsEnabled"];
                        task.IsProcessing = (bool)dr["IsProcessing"];
                        task.IsManualLaunch = (bool)dr["IsManualLaunch"];
                        task.ProcessMachineName = dr["ProcessMachineName"].ToString();
                        task.NextRun = (DateTime)dr["NextRun"];
                        task.PostProcessNotification = (bool)dr["NotifyPostProcess"];
                        task.PreProcessNotification = (bool)dr["NotifyPreProcess"];
                        task.Priority = (TransferParam.Priority)Enum.Parse(typeof(TransferParam.SystemType), dr["PriorityId"].ToString());
                        task.SleepMinutes = (int)dr["SleepMinutes"];
                        task.ScheduleId = (int)dr["ScheduleId"];
                        task.CurrentRuns = (int)dr["CurrentRuns"];
                        task.TotalRuns = (int)dr["TotalRuns"];
    
                        SchedulerTask scheduledTask = new SchedulerTask(new ManualResetEvent(false), task);
                        //Queue up task to worker thread and start
                        ThreadPool.QueueUserWorkItem(new WaitCallback(this.ThreadProc), scheduledTask);     
                    }
                }
            }
    
        }
        catch (Exception ex)
        {
            //Handle
        }
    }
    
    private void ThreadProc(object taskObject)
    {
        SchedulerTask task = (SchedulerTask)taskObject;
        ScheduledTaskEngine engine = null;
        try
        {
            engine = SchedulerTaskEngineFactory.CreateTaskEngine(task.Task, _ConnectionString);
            engine.StartTask(task.Task);    
        }
        catch (Exception ex)
        {
            //Handle
        }
        finally
        {
            task.TaskResetEvent.Set();
            task.TaskResetEvent.Dispose();
        }
    }
    
    public class Example
    {
        private BlockingCollection<string> m_Queue = new BlockingCollection<string>();
    
        public void Start()
        {
            var threads = new Thread[] 
                { 
                    new Thread(Producer), 
                    new Thread(Consumer), 
                    new Thread(Consumer), 
                    new Thread(Consumer) 
                };
            foreach (Thread thread in threads)
            {
                thread.Start();
            }
        }
    
        private void Producer()
        {
            while (true)
            {
                Thread.Sleep(TimeSpan.FromSeconds(5));
                ScheduledTask task = GetScheduledTask();
                if (task != null)
                {
                    foreach (string file in task.Files)
                    {
                        m_Queue.Add(task);
                    }
                }
            }
        }
    
        private void Consumer()
        {
            // Make a connection to the resource that is assigned to this thread only.
            while (true)
            {
                string file = m_Queue.Take();
                // Process the file.
            }
        }
    }