C# 线程池/WaitHandle资源泄漏/崩溃
我想我可能需要重新考虑我的设计。我很难缩小一个导致我的电脑完全挂起的bug,有时会抛出VS2010的HRESULT 0x8007000E 我有一个控制台应用程序(稍后我会将其转换为服务),它处理基于数据库队列的文件传输 我正在限制允许传输的线程。这是因为我们正在连接的某些系统只能包含来自特定帐户的特定数量的连接 例如,系统A只能同时接受3个连接(这意味着3个单独的线程)。这些线程中的每一个都有自己独特的连接对象,因此我们不应该遇到任何同步问题,因为它们不共享连接 我们希望按周期处理来自这些系统的文件。例如,我们将允许3个连接,每个连接最多可以传输100个文件。这意味着,要从系统A中移动1000个文件,我们每个周期只能处理300个文件,因为允许3个线程,每个线程处理100个文件。因此,在这个传输的生命周期内,我们将有10个线程。我们一次只能跑3次。因此,将有3个周期,最后一个周期将只使用1个线程来传输最后100个文件。(3个线程x 100个文件=每个周期300个文件) 当前的架构示例如下:C# 线程池/WaitHandle资源泄漏/崩溃,c#,crash,memory-leaks,threadpool,waithandle,C#,Crash,Memory Leaks,Threadpool,Waithandle,我想我可能需要重新考虑我的设计。我很难缩小一个导致我的电脑完全挂起的bug,有时会抛出VS2010的HRESULT 0x8007000E 我有一个控制台应用程序(稍后我会将其转换为服务),它处理基于数据库队列的文件传输 我正在限制允许传输的线程。这是因为我们正在连接的某些系统只能包含来自特定帐户的特定数量的连接 例如,系统A只能同时接受3个连接(这意味着3个单独的线程)。这些线程中的每一个都有自己独特的连接对象,因此我们不应该遇到任何同步问题,因为它们不共享连接 我们希望按周期处理来自这些系统的
[WaitHandle.WaitAll(transfersArray)]
[transfersArray=new TransferArray[3]
,这是系统A的最大值,但可能因系统而异[WaitHandle.WaitAll(transfersArray)]
WaitHandle.WaitAll(array)
之后循环遍历数组并调用array[index].Dispose()?
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.
}
}
}