我想我可能需要重新考虑我的设计。我很难缩小一个导致我的电脑完全挂起的错误,有时会抛出VS 2010的HRESULT 0x8007000E。线程池/ WaitHandle资源泄漏/崩溃
我有一个控制台应用程序(我将稍后转换为服务)基于数据库队列传输文件。
我限制了允许传输的线程。这是因为我们连接的某些系统只能包含来自特定帐户的一定数量的连接。
例如,系统A只能接受3个同时连接(这意味着3个独立的线程)。这些线程中的每一个都有自己独特的连接对象,所以我们不应该遇到任何同步问题,因为它们没有共享连接。
我们想循环处理来自这些系统的文件。因此,例如,我们将允许3个连接,每个连接最多可传输100个文件。这意味着,要从系统A移动1000个文件,我们每个周期只能处理300个文件,因为每个文件允许3个线程,每个文件有100个文件。因此,在这个转移的整个生命周期中,我们将有10个线程。我们一次只能运行3个。所以,会有3个周期,最后一个周期只会使用1个线程来传输最后的100个文件。 (3个线程×100个=文件每循环300名的文件)
现行的结构通过例子是:
- 甲System.Threading.Timer检查每5秒的东西通过调用GetScheduledTask做队列()
- 如果没有什么,GetScheduledTask()简单地什么也不做
- 如果有工作,创建一个线程池线程来处理工作[工作线程A]
- 工作线程A看到,有1000个文件传输
- 工作线程A看到,它只能有3个线程中运行的系统中,它从
- 工作线程A获取文件启动三个新的工作线程[B,C,d]和转让
- 工作线程用于等待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()?
- 任务管理器下句柄计数此过程中慢慢爬行
- 我打电话工作者线程A的从的System.Threading初始创建。计时器。这会有什么问题吗?该定时器的代码是:
(用于调度一些类代码)
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();
}
}
好像这是一个编码错误,与声明重置事件数组有关。我是做 'ManualResetEvent的[]事件=新ManualResetEvents [统计]' 而不是 '的WaitHandle [] =事件的WaitHandle新[计]' – 2010-07-19 18:16:01