|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
||||
|
||||
CreateThread, SendMessage/PostMessage
Добрый день. Вот и я с вопросом решил обратиться.
Что нужно: 1. Из программы запустить презентацию. 2. Дождаться её завершения. 3. Информировать пользователь я ходе презентации (об ожидании закрытия презентации). С запуском и ожиданием проблем нет. Проблема с продолжением работы программы после закрытия презентации. Код:
function LectureThreadProc(p: Pointer): DWORD; stdcall; var sei: TShellExecuteInfo; Buffer: array[0..1023] of Char; tmp_str: string; stream: TResourceStream; lpHandles: array[0..1] of THandle; begin SetString(tmp_str, Buffer, GetTempPath(Sizeof(Buffer) - 1, Buffer)); tmp_str := Format(LECTURE_FORMAT_FILE, [tmp_str, PThreadParams(p)^.Num]); stream := TResourceStream.Create(HInstance, Format(LECTURE_FORMAT_RESOURCE, [PThreadParams(p)^.Num]), RT_RCDATA); stream.SaveToFile(tmp_str); stream.Free; ZeroMemory(@sei, SizeOf(sei)); sei.cbSize := SizeOf(sei); sei.lpFile := PChar(tmp_str); sei.nShow := SW_SHOWNORMAL; sei.fMask := SEE_MASK_NOCLOSEPROCESS; if ShellExecuteEx(@sei) then begin lpHandles[1] := sei.hProcess; lpHandles[0] := LectureThreadCloseEvent; case WaitForMultipleObjects(2, @lpHandles, False, INFINITE) of WAIT_OBJECT_0: begin TerminateProcess(sei.hProcess, 0); CloseHandle(sei.hProcess); end; WAIT_OBJECT_0 + 1: begin CloseHandle(sei.hProcess); EnterCriticalSection(LectureThreadCS); PostMessage(PThreadParams(p)^.Wnd, WM_LECTURE_CLOSE, 0, 0); LeaveCriticalSection(LectureThreadCS); end; end; end; Windows.DeleteFile(PChar(tmp_str)); Result := 0; ExitThread(Result); end; procedure TMainForm._StartLecture(Number: TChapterNumber); var id: DWORD; begin LectureThreadParams.Wnd := Self.Handle; LectureThreadParams.Num := Number; LectureThreadhandle := CreateThread(nil, 0, @LectureThreadProc, @LectureThreadParams, 0, id); Application.Minimize; end; procedure TMainForm.WMLectureClose(var Message: TMessage); begin WaitForSingleObject(LectureThreadHandle, INFINITE); CloseHandle(LectureThreadHandle); LectureThreadHandle := INVALID_HANDLE_VALUE; Application.Restore; end; все отрабатывает на отлично. Но программа встает колом (не всегда, иногда с 10 запуска потока, иногда со второго). Зависание происходит на строчке: PostMessage(PThreadParams(p)^.Wnd, WM_LECTURE_CLOSE, 0, 0); Причем программа не реанимируется, только жесткое завершение процесса. Если запуска из под ID, то только перезапуск IDE. Уже и секцию критическую добавил и SendMessage заменил на PostMessage. И Тырнет перерыл. Сталкивался кто? Какие еще есть варианты отправить сообщение форме по завершению потока? P.S. Погонял еще. Часто зависает еще до запуска презентации. IDE выдает "External exception EEFFACE". Ну а потом среда отваливается от программы и требует перезапуска. P.P.S. Без PostMessage работает как часы. Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. Последний раз редактировалось dr. F.I.N., 18.05.2016 в 15:14. |
#2
|
||||
|
||||
Все-таки проблема не в отправке сообщений, а в ShellExecuteEx. Почему-то иногда вылетает ошибка "External exception EEFFACE" и все встает колом. Закономерности не нашел.
Думал проблема в потоке, оказалось, что не там. Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
#3
|
||||
|
||||
В общем-то проблема не нова. Интернет-сообщества "жалуются" на ShellExecute. А решение предложено одно - использовать CreateProcess.
С этим все получилось. Сам с собой поговорил Тему можно закрыть. Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
#4
|
|||
|
|||
Ну, у меня вчера вообще что-то форум не работал...
По поводу ShellExecute. Где-то на просторх MSDN это написано. ShellExecute(Ex) лучше всего использовать для того, что бы запустить процесс и "бросить" его. Собственно, ShellRxrcute это обертка над CreateProcess, которая, с одной стороны, добавляет возможности запуска "через реестр" (по типу файла), с другой стороны не имеет всех тех возможностей, что CreateProcess. Кстати, вот еще один момент: Цитата:
|