Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.133.131.168] |
|
Сообщ.
#1
,
|
|
|
Есть следующий код. В функции ОК падает Windows 10, появляется синий экран смерти с сообщением кода остановки системы.
Я связывался с тех поддержкой фирмы МОХА в России, они ничем помочь не могут bool volatile Prervat422Read, IsPotok422Read; Есть поток: UINT Com422PotokRead(LPVOID pParam) { … IsPotok422Read=true; … while (Prervat422Read == false) { … Работа с СОМ422 портом фирмы МОХА } ... IsPotok422Read=false; } Есть функция ОК: void CPultSPNDlg::OnBnClickedOk() { Prervat422Read = true; while (IsPotok422Read == true) Здесь падает система. { Sleep(100); }; }; Что я делаю не правильно? |
Сообщ.
#2
,
|
|
|
Цитата a_n_y_a @ Что я делаю не правильно? На мой взгляд вообще всё. Но падает система явно не здесь. Скорее всего делаешь что-то неправильно при работе с портом, где-то в драйвере падает. Добавлено Кстати, при нажатии OK приложение скорее всего завершается, а завершения потока ты не ждёшь. Попробуй сделать в OnBnClickedOk, после цикла, WaitForSingleObject для потока |
Сообщ.
#3
,
|
|
|
Цитата Олег М @ Цитата a_n_y_a @ Что я делаю не правильно? На мой взгляд вообще всё. Но падает система явно не здесь. Скорее всего делаешь что-то неправильно при работе с портом, где-то в драйвере падает. Добавлено Кстати, при нажатии OK приложение скорее всего завершается, а завершения потока ты не ждёшь. Попробуй сделать в OnBnClickedOk, после цикла, WaitForSingleObject для потока Я не знаю как для потока сделать ожидание с помощью WaitForSingleObject. Если можешь, напиши пожалуйста код. Буду тебе очень благодарен. |
Сообщ.
#4
,
|
|
|
Цитата a_n_y_a @ Я не знаю как для потока сделать ожидание с помощью WaitForSingleObject. Если можешь, напиши пожалуйста код. Буду тебе очень благодарен. HANDLE hThread = reinterpret_cast<HANDLE>(_beginthreadex....... void CPultSPNDlg::OnBnClickedOk() { Prervat422Read = true; //Сообщаем потоку, что пора завершаться ::WaitForSingleObject(hThread, INFINITE); //Ждём завершения потока ::CloseHandle(hThread); //Удаляем хендл }; |
Сообщ.
#5
,
|
|
|
Цитата Олег М @ Цитата a_n_y_a @ Я не знаю как для потока сделать ожидание с помощью WaitForSingleObject. Если можешь, напиши пожалуйста код. Буду тебе очень благодарен. HANDLE hThread = reinterpret_cast<HANDLE>(_beginthreadex....... void CPultSPNDlg::OnBnClickedOk() { Prervat422Read = true; //Сообщаем потоку, что пора завершаться ::WaitForSingleObject(hThread, INFINITE); //Ждём завершения потока ::CloseHandle(hThread); //Удаляем хендл }; Я сделал: CWinThread *Pr; Pr=AfxBeginThread(Com422PotokRead, this); И далее уже ::WaitForSingleObject(Pr->m_..., INFINITE); Вопрос, а удалять хендл обязательно? Если поток закрылся, может хендл удаляется автоматически? Я поставил твой код, все работает и не падает. Большое спасибо за помощь. |
Сообщ.
#6
,
|
|
|
Цитата a_n_y_a @ Вопрос, а удалять хендл обязательно? Если поток закрылся, может хендл удаляется автоматически? CloseHandle надо сделать чтобы очистить память. |
Сообщ.
#7
,
|
|
|
Цитата a_n_y_a @ Вопрос, а удалять хендл обязательно? Если поток закрылся, может хендл удаляется автоматически? Нет, не удаляется. Будет утечка памяти, причём довольно большая - там остаётся стек потока |
Сообщ.
#8
,
|
|
|
Цитата Олег М @ Цитата a_n_y_a @ Вопрос, а удалять хендл обязательно? Если поток закрылся, может хендл удаляется автоматически? Нет, не удаляется. Будет утечка памяти, причём довольно большая - там остаётся стек потока В моем случае достаточно сделать delete Pr; Или надо еще удалять хендл: ::CloseHandle(Pr->m_...) Или надо делать и то и другое? |
Сообщ.
#9
,
|
|
|
Цитата a_n_y_a @ while (IsPotok422Read == true) Здесь падает система. { Sleep(100); }; Никогда так не делай больше! Добавлено Цитата a_n_y_a @ Или надо еще удалять хендл: Тебе уже говорят все. CloseHandle надо обязательно, ну и delete тоже конечно если там объект создавался динамические. Как бы если delete не сделать, то утечка памяти будет на порядки меньше. |
Сообщ.
#10
,
|
|
|
Цитата Олег М @ Цитата a_n_y_a @ Вопрос, а удалять хендл обязательно? Если поток закрылся, может хендл удаляется автоматически? Нет, не удаляется. Будет утечка памяти, причём довольно большая - там остаётся стек потока А почему - стек ? Хэндл можно закрыть сразу, если управлять потоком не нужно. ----- void CPultSPNDlg::OnBnClickedOk() { Prervat422Read = true; //Сообщаем потоку, что пора завершаться ::WaitForSingleObject(hThread, INFINITE); //Ждём завершения потока ::CloseHandle(hThread); //Удаляем хендл }; Это очень неудачный вариант. Его лучше избегать. |
Сообщ.
#11
,
|
|
|
Цитата ЫукпШ @ Это очень неудачный вариант. Его лучше избегать. Почему, в чём неудачность этого варианта? Добавлено Цитата ЫукпШ @ Хэндл можно закрыть сразу, если управлять потоком не нужно. Вот это действительно неудачная и вредная фраза. При вызове CloseHandle поток не будет остановлен, пока сам не завершится. Но лучше до завершения потока его не вызывать, потому что потеряешь контроль над потоком. |
Сообщ.
#12
,
|
|
|
Отлаживаю программу, о которой идет речь. Программа останавливается на точке останова, я правлю код, жму Build, визуальная студия спрашивает остановить ли выполнение программы, я жму ОК, и система падает! Я работаю в VC++ 2017. Видимо те потоки, работающие с СОМ422 портом не закрываются автоматически. В этой ситуации можно что ни будь сделать?
|
Сообщ.
#13
,
|
|
|
Цитата a_n_y_a @ В этой ситуации можно что ни будь сделать? Единственно, что ты можешь здесь сделать - это выяснить падает ли система из-за какой-то твоей ошибки, или драйверы устройства так реагируют на отладчик. Для этого её надо раз сто запустить/остановить без отладчика, если упадёт - ошибка скорее всего у тебя. И скомпилируй в релизе, проверь иоже. |
Сообщ.
#14
,
|
|
|
В случае падения можно (при наличии виртуалки попробовать запустить его там), ну либо на другой машине.
|
Сообщ.
#15
,
|
|
|
Проверил в автономном запуске без студии. Завершаю программу через диспетчер задач. Система не падает! Дело в студии? Или диспетчер задач виртуально нажимает кнопку ОК или Cancel?
|
Сообщ.
#16
,
|
|
|
Цитата Олег М @ При вызове CloseHandle поток не будет остановлен, пока сам не завершится. Ничего подобного. К остановке потока CloseHandle не имеет никакого отношения. Если будет взведён флаг, поток всё равно завершиться. Нельзя будет узнать будет статус потока. Но если это не нужно - можно и закрыть. Добавлено Цитата Олег М @ Почему, в чём неудачность этого варианта? Во всём. void CPultSPNDlg::OnBnClickedOk() { Prervat422Read = true; //Сообщаем потоку, что пора завершаться ::WaitForSingleObject(hThread, INFINITE); //Ждём завершения потока ::CloseHandle(hThread); //Удаляем хендл }; 1. Для остановки потока автор пытается использовать переменную. Она точно "volatile" ? Если для этого имеются объекты ядра (а они имеются), лучше использовать их. Вот это и будет - правильно. 2. Из обработчика кнопки автор пытается дождаться окончания потока. На время ожидания приложение будет просто парализовано. Хорошо, если потребуется 100 ms. А если 5000 ms ? 3. Параметр INFINITE. А если в силу любых причин придётся ждать бесконечно ? (Особенно на этапе создания/отладки приложения) Приложение будет парализовано навсегда. Хотя без этого можно обойтись. Установим T-OUT, дождёмся результата ожидания. Если результат не успешен или ошибка - будем использовать "TerminateThread" и выдадим диагностику. Лучше так, чем просто зависнуть навсегда. 4. CloseHandle. Это всегда можно забыть сделать. Поскольку используется очень часто, лучше сделать класс-оболочку вокруг HANDLE. Тогда многое станет проще и надёжнее. Автор явно не читал Рихтера. При создании таких приложений лучше почитать, тем более, что электронную версию найти не трудно. |
Сообщ.
#17
,
|
|
|
Цитата ЫукпШ @ 1. Для остановки потока автор пытается использовать переменную. Она точно "volatile" ? Вроде у него там присутствует слово volatile, не уверен что на том месте. Цитата ЫукпШ @ Если для этого имеются объекты ядра (а они имеются), лучше использовать их. Вот это и будет - правильно. Это на любителя. Да и всё остальное - тоже. В целом код более-менее правильный. Добавлено Цитата ЫукпШ @ Нельзя будет узнать будет статус потока. Но если это не нужно - можно и закрыть. Статус нафиг никому не нужен. Основное - всегда нужно ждать завершения потока, если ты закроешь хендл, то не сможешь этого сделать. |
Сообщ.
#18
,
|
|
|
Цитата Олег М @ Это на любителя. Да и всё остальное - тоже. В целом код более-менее правильный. Ничего себе - на любителя. Откуда ты знаешь, какой он ? Приложение делается для юзера, а не для программёра. Программа может зависнуть без диагностики и автор прямым образом это делает. Далее, автор начнёт копировать это решение во все свои программы.. Тогда это порочная любовь. ..Как же будет недоволен юзер, когда увидит ни на что не реагирующее окно.. Добавлено Цитата Олег М @ Статус нафиг никому не нужен. Основное - всегда нужно ждать завершения потока, если ты закроешь хендл, то не сможешь этого сделать. А я и не говорю, что это обязательно надо делать. Но это можно делать, если хочется. И со стеком потока CloseHandle никак не связан. |
Сообщ.
#19
,
|
|
|
Проверил в автономном запуске без студии. Завершаю программу через диспетчер задач. Система не падает! Дело в студии? Или диспетчер задач виртуально нажимает кнопку ОК или Cancel?
|
Сообщ.
#20
,
|
|
|
Цитата a_n_y_a @ Проверил в автономном запуске без студии. Завершаю программу через диспетчер задач. Система не падает! Дело в студии? Или диспетчер задач виртуально нажимает кнопку ОК или Cancel? Надо завершать именно по нажатию кнопки OK/Cancel или зарывать окно. Там скорее всего не в студии проблема, а в том, что драйвер устройства как-то неправильно работает под отладчиком. К сожалению, я в этом тоже плохо разбираюсь. |
Сообщ.
#21
,
|
|
|
Цитата a_n_y_a @ Завершаю программу через диспетчер задач. Система не падает! Дело в студии? Если программа "падает" так решительно и есть подозрение на драйвер, значит что можно посоветовать ? Очевидно, надо найти другую программу (-ы), использующую COM-порт. И попробовать её. |