Думаю, мне может потребоваться передумать мой дизайн. Мне сложно сузить ошибку, из-за которой компьютер полностью зависает, иногда бросая HRESULT 0x8007000E из VS 2010.Threadpool/WaitHandle утечка ресурсов/авария
У меня есть консольное приложение (которое я позже преобразую в службу), которое обрабатывает передача файлов на основе очереди базы данных.
Я сжимаю потоки, разрешенные для передачи. Это связано с тем, что некоторые системы, к которым мы подключаемся, могут содержать только определенное количество подключений от определенных учетных записей.
Например, система А может принимать только 3 одновременных соединения (что означает 3 отдельных потока). Каждый из этих потоков имеет свой собственный уникальный объект соединения, поэтому нам не следует запускать какие-либо проблемы с синхронизацией, так как они не используют соединение.
Мы хотим обрабатывать файлы из этих систем в циклах. Так, например, мы разрешим 3 подключения, которые могут передавать до 100 файлов на соединение. Это означает, что для перемещения 1000 файлов из System A мы можем обрабатывать только 300 файлов за цикл, так как разрешено 3 потока по 100 файлов. Поэтому за время жизни этого переноса у нас будет 10 потоков. Мы можем работать только по 3 за раз. Таким образом, будет 3 цикла, и последний цикл будет использовать только 1 поток для передачи последних 100 файлов. (3 нитки х 100 файлов = 300 файлов за цикл)
В настоящее время архитектура примером является:
- System.Threading.Timer проверяет очередь каждые 5 секунд что-то делать, вызывая GetScheduledTask()
- Если нет ничего, GetScheduledTask() просто ничего не делает
- Если есть работа, создать ThreadPool нить для обработки работы [Work нитяных]
- работы Поток а видит, что есть 1000 файлов для передачи
- работа Поток А видит, что он может иметь только 3 темы, работающих в системе он становится все файлы из
- Работа нитяным начинается три новые рабочие темы [B, C, D] и переводы
- Работа Поток А ждет B, C, D
[WaitHandle.WaitAll(transfersArray)]
- Работа Поток А видит, что есть еще несколько файлов в очереди (должно быть 700 сейчас)
- Работа Thread А создает новый массив, чтобы ждать на
[transfersArray = new TransferArray[3]
, которое максимально для системы А, но может варьироваться в зависимости от системы - Рабочая резьба А запускает три новых рабочих резьбы [B, C, D] и ждет их
[WaitHandle.WaitAll(transfersArray)]
- Процесс повторяется, пока больше нет файлов для перемещения.
- сигналы Работа Пронизывайте, что это делается
Я использую ManualResetEvent для обработки сигналов.
Мои вопросы:
- Есть ли вопиющее обстоятельство, которое может вызвать утечку ресурсов или проблема, что я переживаю?
- Должен ли я цикл через массив после каждого
WaitHandle.WaitAll(array)
и вызватьarray[index].Dispose()?
- Количество Handle под Task Manager для этого процесса медленно ползет вверх
- Я зову начальное создание Worker Thread А из 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 [число]' –