On-line: гостей 27. Всего: 27 [подробнее..]
АвторСообщение
постоянный участник




Пост N: 5855
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 14.05.18 21:33. Заголовок: Вылет из программы...


Всем привет !
Как можно в МиниГуи программе сделать вызов своих функций при аварийном завершении программы (т.е. при вылете) ?
Т.е. хочу сделать сразу после появления MsgBox() вызов 2-3 функций и потом сделать DbCloseAll().
Как это реализовать ?

Для чего это нужно, поясню: при входе в свою программу я пишу в базу кто и когда вошел в программу (логин пользователя).
И при выходе из программы, стираю этого пользователя из базы.
Если программа "вылетает", то юзер числится как работающий.
Древнее наследие с клипера, хотел переделать, да так и осталось.

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 234 , стр: 1 2 3 4 5 6 7 8 9 10 11 12 All [только новые]


постоянный участник




Пост N: 8183
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 20.05.26 20:50. Заголовок: Haz пишет: Код запу..


Haz пишет:

 цитата:
Код запуска потока и функцию потока скинь сюда



Перекинул вопрос сюда !
При старте главного окна программы:
      o:Event( 0, {|ow|  // запуск при инициализации окна 
Local owc := ow:Cargo, nMsg := 220, nSek := 10
Local hWnd, cWnd, aPst, i
hWnd := ow:Handle
cWnd := ow:Name
? SPACE(5) + REPL(".", 90)
? SPACE(5) + ":Event(0)", ProcNL(), hWnd, IsIconic( hWnd ), cWnd, _HMG_MainHandle
// запустить отдельный поток для управления файлом семафора xxx.stop
owc:hThr := myThr_Start(cFStop, hWnd, nMsg, nSek)
//DoEvents()
? SPACE(5) + "запустить отдельный поток для семафора xxx.stop", cFStop, ow:Name, nMsg, nSek
?? "owc:hThr=", owc:hThr
aPst := {1,2,3,4,15,5}
For i := 1 To Len(aPst)
_wSend(aPst, ow) // запуск события XX
DO EVENTS
Next
? REPL(".", 90 ) ; ? ProcNL()
? SPACE(3) + "ОЖИДАНИЕ ВВОДА В ПРОГРАММУ "
Return Nil
})
....
////////////////////////////////////////////////////////////////////////////
// Потоковые функции в MiniGui
FUNCTION myThr_Start(cFile, hWnd, nMsg, nSek)
LOCAL cMsg

IF ! hb_mtvm()
cMsg := "Многопоточность не поддерживается!;"
cMsg += "Ключ компиляции программы -mt !;"
AlertStop( cMsg, App.ExeName , , 64, {RED} )
? cMsg
RETURN 0
ENDIF

Default nMsg := 220, nSek := 2

RETURN hb_threadStart( HB_THREAD_INHERIT_MEMVARS, @myThr_File(), cFile, hWnd, nMsg, nSek )

FUNCTION myThr_Stop(hThr)

IF !Empty(hThr) ; hb_threadDetach( hThr )
ENDIF

RETURN NIL

FUNCTION myThr_File(cFile, hWnd, nMsg, nSek)
LOCAL lFile, cRun, cPar, lPost := .T.
LOCAL cFileExe := "xxx.exe" // прога на C#
LOCAL cFileTerm := "xxx4.exe" // прога на терминалке

? ProcNL(), HB_DATETIME(), "<<<", cFile, hWnd, nMsg, nSek, lPost
?? "IsIconic()=", IsIconic(hWnd)

DO WHILE .T.
IF lPost .and. ( lFile := hb_FileExists(cFile) )
? REPL("#.stop",20)
cRun := "taskkill.exe"
cPar := " /T /F /IM " + cFileExe
ShellExecute( 0, 'open', cRun, cPar, , SW_HIDE )
? SPACE(3)+"-> " + cRun + " " + cPar + " - " + TIME()
wApi_Sleep(200)
cPar := " /T /F /IM " + cFileTerm
ShellExecute( 0, 'open', cRun, cPar, , SW_HIDE )
? SPACE(3)+"-> " + cRun + " " + cPar + " - " + TIME()
wApi_Sleep(200)
DO EVENTS
PostMessage( hWnd, WM_WND_LAUNCH, nMsg, 0 )
lPost := .F.
ENDIF
// wait nSek секунд
DO EVENTS ; wApi_Sleep(1000 * nSek ) ; DO EVENTS

? ProcNL(), "<<<", HB_DATETIME(), cFile, lFile, lPost
ENDDO

RETURN NIL


Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2050
Зарегистрирован: 20.02.11
ссылка на сообщение  Отправлено: 20.05.26 22:15. Заголовок: Andrey пишет: Перек..


Andrey пишет:

 цитата:
Перекинул вопрос сюда


Этот код не должен валить tsbrowse, но есть нюансы
1. Поток никогда не завершится в такой реализации
. после первого убиения процессов, файл семафора xxx.stop
. будет игнорироваться
2. Поток не указан как join или detach что не есть хорошо
3. myThr_Stop() если где-то вызывается это не остановка потока,
а отсоединение от основного процесса, далее см п. 1
4. Какой смысл в потоке после убиения двух процессов?
Поток будет молотить бесконечно вызывая каждые 2 секунды пару doevents() и игнорить семафор
там где надо и не надо. и опять см п. 1
5.Ну и без мютекса вывод в лог через ? ....
Может вызвать конфликт с попыткой вывода из основного процесса

Возможно все это и может спровоцировать ошибку.
Что лучше сделать в этом примере
1. при создании потока сразу его отсоединить детачем
2. цикл while . t. заменить на while lPost
Тогда event:0 запустится поток, дождется семафора, убъет указанные процессы и завершит работу освободив ресурсы
3.Вывод в лог через ? ... лучше делать через мютекс

Спасибо: 0 
ПрофильЦитата Ответить
moderator




Пост N: 2546
Зарегистрирован: 11.02.10
ссылка на сообщение  Отправлено: 21.05.26 15:07. Заголовок: Haz пишет: Что лучш..


Haz пишет:

 цитата:
Что лучше сделать в этом примере




Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 8184
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 22.05.26 15:37. Заголовок: Haz пишет: 4. Какой..


Haz пишет:

 цитата:
4. Какой смысл в потоке после убиения двух процессов?


Немного уточнение к коду.
При появлении файла семафора xxx.stop - убиваются 2 процесса и прога потом завершается.
При завершении проги уже все ресурсы освободятся.
Не понял пункты 1 и 3 ?
Можно ли более подробно написать ?

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2051
Зарегистрирован: 20.02.11
ссылка на сообщение  Отправлено: 22.05.26 18:04. Заголовок: Andrey пишет: Не по..


Andrey пишет:

 цитата:
Не понял пункты 1 и 3 ?


1 цикл потока вечный , нет условия завершения потока даже после обнаружения семафора.
. при этом поток нии свободный ни присоединённый
3 детач не завершает поток

Хотя бы deepseek сприси
Если поток в Harbour не отсоединён (hb_threadDetach) и к нему не присоединились с помощью hb_threadJoin, это может привести к утечке системных ресурсов и создать так называемый «zombie-поток».

Обычно эта проблема выглядит как постепенная утечка памяти и дескрипторов, которая может замедлить систему или привести к аварийному завершению программы при большом количестве таких потоков. Это не приводит к мгновенному сбою, но последствия для долго работающих приложений могут быть серьёзными:

· Утечка критических ресурсов: Harbour создаёт «присоединяемый» поток. Когда он завершается, его стек освобождается, но жизненно важные структуры (идентификатор потока, код возврата и т.д.) остаются в памяти до вызова hb_threadJoin или hb_threadDetach.
· Невозможно создать новый поток: При исчерпании системных лимитов могут возникать ошибки вроде EAGAIN при создании нового потока, а также ошибки создания мьютексов или других объектов ядра.
· Риск зависания приложений: Постоянное потребление ресурсов без освобождения со временем приводит к нестабильной работе или аварийному завершению программы.

Чтобы этого избежать, достаточно придерживаться простого правила: для каждого созданного потока нужно либо вызвать hb_threadDetach, если результат не нужен, либо hb_threadJoin, когда важно дождаться его выполнения и освободить ресурсы.
Некоторые разработчики ошибочно полагают, что достаточно просто «забыть» о потоке, но это прямой путь к проблемам. Как лучше поступить в вашей конкретной ситуации — сразу отсоединить поток, если его результат не нужен, или корректно присоединить его?

Если 1 и 3 относятся к рекомендациям, то в документации Александра , есть и описание и примеры работы с детачем и мютексами. Все в разделе многопоточность
Если коротко, то поток не может быть ничей ни detach ни , join
А мутексы это семафорчики для потока обозначающие блокировку работы с разделяемыми ресурсами. Вывод в лог это разделяемый ресурс файл


.

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 8301
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 22.05.26 18:56. Заголовок: Haz пишет: Если пот..


Haz пишет:

 цитата:
Если поток в Harbour не отсоединён (hb_threadDetach)


Хочешь сказать что такая конструкция опасна ?
 
threadD:=hb_threadStart(HB_THREAD_INHERIT_MEMVARS,@MyFunc())
do while lastkey()#27
inkey(0)
enddo

IF hb_IsPointer(threadD)
hb_threadJoin( threadD )
endif


Прога работает месяцами (пока обнова не понадобится), ни чего не падает и
зомби-потоков не видел
MyFunc() много чего делает....

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 8185
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 22.05.26 19:00. Заголовок: Есть пример у Григор..


Есть пример у Григория C:\MiniGUI\SAMPLES\Advanced\Tsb_2WndType
который я сделал благодаря Сергею, вот там и реализована подобная схема, может и неправильно сделал, но работает.
Очень хочется видеть ПРАВИЛЬНОЕ использование потоков в МиниГуи, чтобы и другие могли это использовать.
Большая просьба к Haz поправить этот пример.

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2052
Зарегистрирован: 20.02.11
ссылка на сообщение  Отправлено: 22.05.26 19:37. Заголовок: Dima пишет: Хочешь ..


Dima пишет:

 цитата:
Хочешь сказать что такая конструкция


Дим, потоки в GUI и CONSOLE ведут себя по разному
В GUI более жёсткие требования, и то что пролетает со свистом в консоли может встать колом гуи
Вообще этике предполагает потоки либо джойнить либо детачить
Пример код Андрея выше, там нет ничего явного что можно связать с tsbrowse и потоком, но вылет есть.
Более того , язык медленно, но развивается, могут ужесточить проверки и оптимизировать код и тогда все что работало годами валиться без предупреждения
Это тоже из личного опыта говорю. Хуже нет разбираться со своим старым кодом . проще заново написать.

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 8303
Зарегистрирован: 17.05.05
ссылка на сообщение  Отправлено: 22.05.26 19:50. Заголовок: Haz пишет: Хуже нет..


Haz пишет:

 цитата:
Хуже нет разбираться со своим старым кодом . проще заново написать.


100 %

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 4887
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 22.05.26 20:37. Заголовок: Haz пишет потоки либ..


Haz пишет
 цитата:
потоки либо джойнить либо детачить


У Андрея, должен быть hb_threadDetach(), в примере он есть. При входе в окно (ON INIT ... :Event( 0... thread создается, в ON RELEASE ... это :Event(90,... делается myThr_Stop(ow:Cargo:hThr), т.е. hb_threadDetach( hThr ) перед другими командами). При срабатывании потока на файл, в событии nMsg работа окна завершается.
По мне thread не причем, тсб валится по др. причинам. Лог, конечно надо вести через мютекс или общую переменную, например (пример был)
PUBLIC o_Thr ; o_Thr := TThrData():New() // создадим контейнер для работы с потоками // create a container for working with streams
но видно не зашло

Спасибо: 0 
ПрофильЦитата Ответить
администратор




Пост N: 2053
Зарегистрирован: 20.02.11
ссылка на сообщение  Отправлено: 22.05.26 21:05. Заголовок: SergKis пишет: У Ан..


SergKis пишет:

 цитата:
У Андрея, должен быть hb_threadDetach


Может быть, но код не представлен
SergKis пишет:

 цитата:
ON RELEASE ... это :Event(90,... делается myThr_Stop(ow:Cargo:hThr), т.е. hb_threadDetach( hThr ) перед другими командами


Сергей , а какой смысл в детаче потока после выполнения задачи? Так он после окна также останется молотить в холостую пока программа не завершится

Детач этого потока нужно делать сразу после открытия
hb_threadDetach((hb_threadStart()), а после выполнения задачи потока(поймали ххх. stop) прерывать цикл. завершая поток
И более того даже поток здесь нужен другой, не постоянно крутящийся, а запускающийся по событию сторожа изменения целевого каталога.
Тогда поток стартанет проверит появился ли ххх. stop и завершится.
Паша давно кидал код сторожа.

что касается причин ошибки, из куска кода tab не при делах, но все же порядок навести надо.
И есть сомнения , что errorsys вообще правильно в могопоточке словит ошибку. К примеру в потоке деление на ноль, а программа живёт и что поток сдох никак не узнать. Каких только чудес не насмотрелся пока вендинговый аппарат приучал к картам emmarine.

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 4888
Зарегистрирован: 17.02.12
ссылка на сообщение  Отправлено: 22.05.26 21:31. Заголовок: Haz пишет какой смыс..


Haz пишет
 цитата:
какой смысл в детаче потока после выполнения задачи?


Это к Андрею - его мысли.
Для задачи Андрея (определять файл), поток не нужен, совсем. А на окне, пока оно существует, существует и поток, вполне нормальный вариант (отрабатывать запросы окна, например)

 цитата:
Каких только чудес не насмотрелся


Если вспоминать историю работы потоков, начиная с clipper, когда надо было переписывать код потока (правила менялись), выкинул их из употребления. Надо поток, запускаю в фоне прогу и общайся с ней как надо, убирай, когда не надо и ... голова не болит, общие правила.
Это к правилам потоков
 цитата:
И есть сомнения , что errorsys вообще правильно в могопоточке словит ошибку. К примеру в потоке деление на ноль, а программа живёт и что поток сдох никак не узнать



Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 8186
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: 23.05.26 19:04. Заголовок: Haz пишет: Детач эт..


Haz пишет:

 цитата:
Детач этого потока нужно делать сразу после открытия
hb_threadDetach((hb_threadStart()), а после выполнения задачи потока(поймали ххх. stop) прерывать цикл. завершая поток
И более того даже поток здесь нужен другой, не постоянно крутящийся, а запускающийся по событию сторожа изменения целевого каталога.
Тогда поток стартанет проверит появился ли ххх. stop и завершится.
Паша давно кидал код сторожа.


Есть готовый пример у Григория C:\MiniGUI\SAMPLES\Advanced\Tsb_2WndType
Там есть кнопка Stop - это для админа, нажимаем и прога завершается,
т.е. тестировка режима завершения программы у всех юзеров работающих с программой.
Сделано специально в отдельном потоке, для показа работы в МиниГуи с потоками, примеров в библиотеке очень мало.
Вопрос ко всем - как правильно реализовать такой режим, чтобы потом это можно добавлять в свои проекты ?

Спасибо: 0 
ПрофильЦитата Ответить
постоянный участник




Пост N: 8188
Зарегистрирован: 12.09.06
ссылка на сообщение  Отправлено: Вчера 11:10. Заголовок: Перешёл на новую вер..


Перешёл на новую версию 26.05 Pro
Один юзер в программе, других открытых программ нет.
Что-то стал падать рабочий код, раньше такого не было.
Ошибка по GETWINDOWRECT примерно так:
      Time from start: 0 days 0 hours 1 mins 34 secs 
Error BASE/3012 Failed to get window rect: GETWINDOWRECT Args: [1] = N 0 [2] = N 3
--------------------------------- Stack Trace ---------------------------------
Called from GETWINDOWRECT(0)
Called from (b)TCONTROL(0)
Called from TSBROWSE:NWIDTH(0)
Called from TSBROWSE:DRAWLINE(0)
Called from TSBROWSE:GOTOP(0)
Called from TSBROWSE:RESET(0)
Called from MAINCARDTABLE(4173) in module: Source\Tbrw_table.prg
Called from MYACTIONENTER(1933) in module: Source\Tbrw_table.prg
Called from (b)FORM_MYTABLE(853) in module: Source\Tbrw_table.prg
Called from DO_WINDOWEVENTPROCEDURE(0)
Called from TWNDDATA:DOEVENT(0)
Called from DO_ONWNDLAUNCH(0)

По коду это так:
         oBrw:Reset()       <<<--------------------  MAINCARDTABLE(4173)

Т.е. нахожусть в ТСБ, открываю карточку по одной записи,
потом закрываю карточку и делаю по ТСБ oBrw:Reset(), далее вылет.
Почему ?
Может нужно как то переключиться заново на ТСБ ?

Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 234 , стр: 1 2 3 4 5 6 7 8 9 10 11 12 All [только новые]
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают: гостей: 1
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 128
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет