DWORD st;
for (int i = 1; i <= pwth.GetSize(); i++)
{
if (pwth[i] != NULL)
{
::TerminateThread(pwth[i]->m_hThread, st);
::CloseHandle(pwth[i]->m_hThread);
delete pwth[i];
}
}
Данная процедура происходит периодически и после достаточно большого количества итераций выдает сообщение "Ошибка создания потока расчета".
Поскольку используется m_bAutoDelete=false, то явно просматривается проблема некорректного удаления объекта CWinthread. Как это сделать корректно.
При попытке использования delete pwth[i] выдает ошибку. CAVector — самопальный массив.
Предлагаю создавать рабочие потоки напрямую через CreateThread или (_beginthread). В данном случае mfc-ые потоки не нужны.
А вообще странно что delete pwth[i] выдает ошибку. Кстати что за ошибка ?
Может оператор [] в самопальном массиве как-то криво реализован?
И кстати в цикле не нужны вызовы TerminateThread() и CloseHandle(). Первый — потому что поток уже завершился, второй — потому что CloseHandle вызывается в деструкторе CWinThread
А вообще можно сократить твой код до примерно такого:
// Вектор не из голых указателей, а из смарт. Когда сам вектор будет уничтожен - он автоматом вызовет delete для указателей
std::vector<std::unique_ptr<CWinThread*>> pwth;
// вектор гарантирует что все элементы будут лежать в памяти в одном непрерывном куске памяти
// так что создавать третий массив для WaitForMultipleObjects не требуется.
std::vector<HANDLE> hnd;
for (size_t i = 0; i <= GetCPUNumber; ++i) {
CWinThread *pthread = AfxBeginThread(proc, NULL, THREAD_PRIORITY_BELOW_NORMAL, NULL, CREATE_SUSPENDED);
if (!pthread) {
AfxMessageBox(_T("Ошибка создания потока расчета"));
return;
}
pthread->m_bAutoDelete = false;
pwth.push_back(std::make_unique<CWinThread*>(pthread));
hnd.push_back(pthread->m_hThread);
pthread->ResumeThread();
}
WaitForMultipleObjects(GetCPUNumber, &hnd[0], true, INFINITE);
Здравствуйте, rus blood, Вы писали:
RB>Полагаю, 6, invalid handle...
Логично, учитывая что перед удалением автор принудительно закрывает хэндл.
Но быстро глянув в исходники MFC вроде там не проверяется результат CloseHandle в деструкторе, как эта ошибка может себя проявить ?
Здравствуйте, ahaos, Вы писали:
A> pwth[i]=AfxBeginThread(CalculatePeriodicCukP,(LPVOID)pi,THREAD_PRIORITY_BELOW_NORMAL,NULL,CREATE_SUSPENDED);
A> delete pwth[i];
Еще бы. Закрывать поток надо AfxEndThread, а вовсе не delete
AfxBeginThread creates a new CWinThread object, calls its CreateThread function to start executing the thread, and returns a pointer to the thread. Checks are made throughout the procedure to make sure all objects are deallocated properly should any part of the creation fail. To end the thread, call AfxEndThread from within the thread, or return from the controlling function of the worker thread.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Еще бы. Закрывать поток надо AfxEndThread, а вовсе не delete
Ни в коем случае. Эту функцию нужно звать только из того потока который хотим завершить. Там же в документации все четко расписано.
AfxBeginThread создает новый объект CWinThread при помощи обычного new. Если b_autodelete в потоке равно true, то после завершения рабочего потока, он сам себя уничтожает с использованием delete this.
В общем поток созданный с помощью CWinThread *t = AfxBeginThread с установленным b_autodelete = false, после завершения собственно потока нужно просто грохнуть delete t. И все, то что у ТС какие-то ошибки лезут — это что-то напортачено в другом месте.
Я приводил кусок кода со стандартным вектором и умным указателем — все работает и корректно удаляется.
И вообще, я еще раз повторю, что нафиг тут не уперлись MFC потоки. _beginthreadex или CreateThread в руки. Может в MFC баг какой-нибудь.
Здравствуйте, Evgeniy Skvortsov, Вы писали:
ES>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>Еще бы. Закрывать поток надо AfxEndThread, а вовсе не delete
ES>Ни в коем случае. Эту функцию нужно звать только из того потока который хотим завершить. Там же в документации все четко расписано.
Да, согласен. Тем не менее насчет delete там ничего нет.
ES>AfxBeginThread создает новый объект CWinThread при помощи обычного new. Если b_autodelete в потоке равно true, то после завершения рабочего потока, он сам себя уничтожает с использованием delete this.
Именно.
ES>И вообще, я еще раз повторю, что нафиг тут не уперлись MFC потоки. _beginthreadex или CreateThread в руки. Может в MFC баг какой-нибудь.
Да нет тут багов скорее всего, просто delete не нужен.
_beginthreadex можно, конечно. CreateThread не стоит — не поставишь в известность CRT, а она хочет знать о появлении нового потока.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Да, согласен. Тем не менее насчет delete там ничего нет.
Да, явно не написано что нужно звать delete, однако там есть такая фраза:
Set the m_bAutoDelete data member to FALSE. This allows the CWinThread object to survive after the thread has been terminated. You can then access the m_hThread data member after the thread has been terminated. If you use this technique, however, you are responsible for destroying the CWinThread object because the framework will not automatically delete it for you.
По моему очень прямой намек, что надо руками удалять экземпляр CWinThread.