Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.188.142.146] |
|
Страницы: (4) 1 2 [3] 4 все ( Перейти к последнему сообщению ) |
Сообщ.
#31
,
|
|
|
Не, я про историю их создания. В MSDN явно говорится, что EnterCriticalSection() в доXPёвом окружении может бросить исключение в случае критически малого количества памяти, но не говорится, какого.
P.S. Однако оно упоминается в InitializeCriticalSection() в подобной же ситуации, и это STATUS_NO_MEMORY. Причём с Висты оно там уже устранено, скорее всего посредством как раз предсозданного ключевого события. |
Сообщ.
#32
,
|
|
|
Вот и я об этом. Прежде, чем их делать, поинтересуемся ценой вопроса. Эта цена - 5 функциональных строк, а именно: 1. Запуск остановленного процесса 2. Преобразование ID в строку 3. Сложение 2-х строк - постоянного имени + ID 4. Создание именованного объекта синхронизации 5. Запуск процесса --- Невыгодно связываться с чем-то ещё. Просто нет необходимости. |
Сообщ.
#33
,
|
|
|
По-твоему, получение hex-значения из командной строки и преобразование в HANDLE сложнее?
|
Сообщ.
#34
,
|
|
|
Цитата Qraizer @ По-твоему, получение hex-значения из командной строки и преобразование в HANDLE сложнее? Нет. Но это значение ещё где-то надо брать, в виде общего счётчика. А в многопоточном приложении - ещё и общей критической секции для этого счётчика. Нет удобства делать классы, объединённые этими статическими членами. я бы сделал, если бы иного пути не было. Именно этот вариант получается при наличии CREATE_SUSPENDED. Всё логично. Добавлено я хочу, чтобы при удачном добавлении элемента в очередь, автоматически возбуждалось событие. Чтобы этой деятельностью больше никто не занимался. |
Сообщ.
#35
,
|
|
|
Да какая разница: командная строка или CREATE_SUSPENDED? Кому как удобнее.
Командная строка тоже может быть забита какими-то параметрами. Тогда можно, конечно, сделать CreateFileMapping+MapViewOfFile (для передачи хендла), но проще ли это? Я не понимаю, почему такой негатив к CREATE_SUSPENDED... Что в нём плохого? |
Сообщ.
#36
,
|
|
|
Почему негатив-то? Просто ему не удаётся найти незаменимого применения, от чего от выглядит ненужным.
|
Сообщ.
#37
,
|
|
|
Цитата Qraizer @ Ты хочешь сказать, на CreateEvent + if (ошибка) + WaitForSingleObject + if (ошибка) ExitThread + висящий event (либо надо придумывать куда ещё CloseHandle засунуть, например, делать счётчик, который будет уменьшаться через atomic-инструкции)?Всё это не актуально. Просто любой CREATE_SUSPENDED легко заменяется на WaitFor...() при старте. Очень удобно, спору нет Добавлено Есть достаточно вещей, которые не являются незаменимыми, но являются более удобными, чем другие. |
Сообщ.
#38
,
|
|
|
А ты точно меня читал?
|
Сообщ.
#39
,
|
|
|
Цитата Jin X @ Да какая разница: командная строка или CREATE_SUSPENDED? Кому как удобнее. Командная строка тоже может быть забита какими-то параметрами. Тогда можно, конечно, сделать CreateFileMapping+MapViewOfFile (для передачи хендла), но проще ли это? Я не понимаю, почему такой негатив к CREATE_SUSPENDED... Что в нём плохого? Тот пример, который привёл ЫукпШ - это пример того, как размазать логику тонким слоем по разным модулям. Единственное для чего может понадобиться CREATE_SUSPENDED - это установить какие-то свойства процесса/потока до его запуска. Причём, в std::thread и pthreads вообще нет возможности создать поток остановленным. |
Сообщ.
#40
,
|
|
|
Цитата Qraizer @ Ну цитата ж твоя А ты точно меня читал? А как иначе использовать WaitFor для того, чтобы запустить "дополнительные" потоки после инициализации чего-либо из "главного" потока? Я говорю о необратимой инициализации типа удаления файла, передачи данных по сети. Которая не нужна в случае неудачной инициализации. p.s. Кстати, я ещё забыл добавить в сценарий... Цитата Jin X @ обработку ситуации, когда инициализация не удалась... CreateEvent + if (ошибка) + WaitForSingleObject + if (ошибка) ExitThread + висящий event Добавлено Ну или когда нужно стартовать все потоки с idle-приоритетом. |
Сообщ.
#41
,
|
|
|
Цитата Jin X @ Во-первых, зачем запускать поток, который ещё надо будет извне подкрутить? Почему бы не подкрутить до запуска? Во-вторых, если поток должен инициализироваться сам, то аварийный выход – это будет его задача, и выполняться она должна в неспящем состоянии. О чём вообще вопрос?А как иначе использовать WaitFor для того, чтобы запустить "дополнительные" потоки после инициализации чего-либо из "главного" потока? Цитата Jin X @ Тут и там выше я не понял, что это значит. Необходимые события создаются по-любому, и если что-то пошло не так, приложение не может функционировать дальше. Все сторонние инициализации выполняются по старту, до запуска любого потока. О чём вопрос?p.s. Кстати, я ещё забыл добавить в сценарий... Цитата Jin X @ Все деинициализации выполняются по выходу, после завершения любых потоков. Зачем счётчики? В чём проблема? либо надо придумывать куда ещё CloseHandle засунуть, например, делать счётчик, который будет уменьшаться через atomic-инструкции |
Сообщ.
#42
,
|
|
|
Qraizer, конкретная задача: запустить 10 потоков с idle приоритетом. Чтобы они сразу были idle. Как это сделать без SUSPEND_THREAD?
|
Сообщ.
#43
,
|
|
|
Пусть каждая делает себе в начале MainThreadProc(), до начала любых полезных действий. Один нормалприорити стэйтмент сложно будет пережить?
Добавлено // Структура с информацией о потоках struct ThreadInfo { HANDLE hThread[THREAD_COUNT]; // хендлы потоков HANDLE evPause[THREAD_COUNT]; // хендлы событий о паузах }; ThreadInfo ioThreads; // информация о потоках CRITICAL_SECTION CriticalSection; // объект критической секции HANDLE events[2]; // общие события: "поступили данные для обработки" и "сигнал выхода" DWORD WINAPI MainThreadProc(LPVOID lpParam) { int idx = (int)lpParam; // наш индекс в массивах SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE); for (;;) { if (WaitForSingleObject(ioThreads.evPause[idx], INFINITE) == WAIT_FAILED) break; // обработка паузы if (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0) break; // одно из двух событий // Выполнение основной процедуры цикла ioThreadProc[idx](); } ExitThread(WaitForSingleObject(evExit, 0) == 0 ? 0 : 1); } int CreateThreads() { int i; for (i = 0; i < THREAD_COUNT; ++i) { ioThreads.evPause[i] = CreateEvent (NULL, TRUE, TRUE, NULL); // событие паузы (signaled == нет паузы) // старт нитки if (ioThreads.evPause[i]!= NULL) ioThreads.hThread[i] = CreateThread(NULL, 0, &MainThreadProc, LPVOID(i), 0, NULL); if (ioThreads.hThread[i] == NULL) // по ошибке досрочно прекращаем { CloseHandle(ioThreads.evPause[i]); break; } } return i; // возвращаем количество запущенных ниток } bool FinishThreads(int Wait = FINISH_THREADS_WAIT_TIME, bool Force = FALSE) { SetEvent(evExit); // всем выход int result = WaitForMultipleObjects(amount, ioThreads.hThread, TRUE, Wait); // ждём завершения потоков if (result == WAIT_TIMEOUT && Force) // если послушались за отведённое время И заставляют for (int i = 0; i < amount; ++i) if (WaitForSingleObject(ioThreads.hThread[i], 0) == WAIT_TIMEOUT) // проверяем статус ... TerminateThread(ioThreads.hThread[i], 1); // ... и стопаем for (int i = 0; i < amount; ++i) { CloseHandle(ioThreads.evPause[i]); CloseHandle(ioThreads.hThread[i]); } return (result == WAIT_OBJECT_0); } void ContinueThread(int idx) { SetEvent(ioThreads.evPause[idx]); } void StopThread(int idx) { ResetEvent(ioThreads.evPause[idx]); } int main() { InitializeCriticalSection(&CriticalSection); evData = CreateEvent(NULL, FALSE,FALSE, NULL); evExit = CreateEvent(NULL, TRUE, FALSE, NULL); // Создание и запуск потоков if (evData == NULL || evExit == NULL) goto quit; events[0] = evExit; events[1] = evData; amount = CreateThreads(); /* ... */ ForceFinishThreads(); quit: CloseHandle(evExit); CloseHandle(evData); DeleteCriticalSection(&CriticalSection); } Добавлено Не проверял. Даже не компилил. |
Сообщ.
#44
,
|
|
|
Qraizer, ok
|
Сообщ.
#45
,
|
|
|
Архитектура немного странная. С одной стороны, нитки запускаются для выполнения каких-то действий, которые вроде бы не зависят от того, какая конкретно нитка отреагирует на какое конкретно действие, но с другой – в приложение заложена архитектура пониточного управления. В условиях полной взаимозаменяемости ниток это кажется избыточным. Либо нитки всё-таки каждая с особенностями, но тогда и передача данных на обработку должна быть направленной, либо нет необходимости паузить отдельные конкретные нитки, но возможно есть необходимость сразу все. Тогда достаточно будет одного события evPause, и код будет немного проще.
Добавлено P.S. Подправил код. Неверно пауза обрабатывалась. Добавлено P.P.S. Ошибок было... не одна. |