Автор | Сообщение |
|
| moderator
|
Пост N: 450
Зарегистрирован: 06.07.06
|
|
Отправлено: 28.11.12 14:07. Заголовок: Harbour для начинающих
Просто сообщаю, что я кардинально обновил одноименную страницу у себя на сайте: http://www.kresin.ru/hrbfaq.html, существенно пополнил (и продолжаю понемногу пополнять) раздел "Отличия от Клиппера".
|
|
|
Новых ответов нет
, стр:
1
2
3
4
5
6
7
8
All
[см. все]
|
|
|
| постоянный участник
|
Пост N: 7001
Зарегистрирован: 12.09.06
|
|
Отправлено: 20.07.21 10:47. Заголовок: Здравствуйте. Очень..
Здравствуйте. Очень мало документации по переменным времени. Можете сделать отдельный раздел у себя в справке ? Чтобы было в одном месте. tDtm := HB_DATETIME() ? HB_TSTOSTR( tDtm ) // 2021-07-19 00:28:52.946 "C" ? HB_TTOC( tDtm ) // 19.07.2021 00:28:52.946 "C" ? HB_TTOD( tDtm ) // 19.07.2021 "D" ? HB_TTON( tDtm ) // 2459415.02 "N" ? HB_TTOS( tDtm ) // 20210719002852946 "C" cDtm := HB_TSTOSTR( tDtm ) ? HB_STRTOTS( cDtm ) // 2021-07-19 00:28:52.946 "T" ? HB_CToT(cDtm) // 00:28:52.946 "T" cTm1 := cTm2 := "" ? tDtm := HB_DATETIME() // 2021-07-19 00:28:52.949 "T" ? tUtc := hb_TSToUTC( tDtm ) // 2021-07-18 21:28:52.949 "T" HB_TTOD( tDtm, @cTm1, "hh:mm:ss.fff" ) HB_TTOD( tUtc, @cTm2, "hh:mm:ss" ) ? cTm1 // 00:28:52.949 "C" ? cTm2 // 21:28:52 "C"
|
|
|
|
| |
Пост N: 1708
Зарегистрирован: 20.02.11
|
|
Отправлено: 20.07.21 11:59. Заголовок: Andrey пишет: Очень..
Andrey пишет: цитата: | Очень мало документации по переменным времени. Можете сделать отдельный раздел у себя в справке ? Чтобы было в одном месте |
| тогда тут дублировать весь хелп по харбуру придется. Зачем ? достаточно где есть https://github.com/Petewg/harbour-core/wiki/hb_T Более того в ChangeLog.txt по Harbour эти функции прекрасно документированы * harbour/source/rtl/dateshb.c + added new .prg functions to mange date and timestamp values: HB_DATETIME() -> <tTimeStamp> HB_CTOD( <cDate> [, <cDateFormat> ] ) -> <dDate> HB_DTOC( <dDate> [, <cDateFormat> ] ) -> <cDate> HB_NTOT( <nValue> ) -> <tTimeStamp> HB_TTON( <tTimeStamp> ) -> <nValue> HB_TTOC( <tTimeStamp>, [ <cDateFormat> ] [, <cTimeFormat> ] ) -> <cTimeStamp> HB_CTOT( <cTimeStamp>, [ <cDateFormat> ] [, <cTimeFormat> ] ) -> <tTimeStamp> HB_TTOS( <tTimeStamp> ) -> <cYYYYMMDDHHMMSSFFF> HB_STOT( <cDateTime> ) -> <tTimeStamp> <cDateTime> should be in one of the above form: - "YYYYMMDDHHMMSSFFF" - "YYYYMMDDHHMMSSFF" - "YYYYMMDDHHMMSSF" - "YYYYMMDDHHMMSS" - "YYYYMMDDHHMM" - "YYYYMMDDHH" - "YYYYMMDD" - "HHMMSSFFF" - "HHMMSSF" - "HHMMSS" - "HHMM" - "HH" Important is number of digits.
|
|
|
|
| постоянный участник
|
Пост N: 7002
Зарегистрирован: 12.09.06
|
|
Отправлено: 20.07.21 12:22. Заголовок: Haz пишет: Более то..
Haz пишет: цитата: | Более того в ChangeLog.txt по Harbour эти функции прекрасно документированы |
| Блин, а я искал по всему инету, вместо того чтобы первоисточник посмотреть... И поиск правильно нужно делать, я искал "HARBOUR hh:mm:ss"
|
|
|
|
| постоянный участник
|
Пост N: 7374
Зарегистрирован: 12.09.06
|
|
Отправлено: 17.05.23 18:22. Заголовок: На сайте у вас есть:..
На сайте у вас есть: 3.13.6 Управление запуском процессов nResult := hb_ProcessRun( cCommand, [cStdIn], [@cStdOut], [@cStdErr], [lDetach] ) handle := hb_ProcessOpen( cCommand, [cStdIn], [@cStdOut], [@cStdErr], [lDetach] ) nResult := hb_ProcessValue( handle, [lWait] ) nResult := hb_ProcessClose( handle, lGentle ) А можно более подробнее дать параметры ? Я использую то что здесь на форуме давали: hPID := hb_processOpen( cRun + " " + cParam,,,,.F., @hProcess) Может и неправильно... nResult := hb_ProcessClose( handle, lGentle ) - возвращает логическую переменную ! Не понял почему ?
|
|
|
|
| moderator
|
Пост N: 1494
Зарегистрирован: 06.07.06
|
|
Отправлено: 18.05.23 09:45. Заголовок: Описаний нигде нет, ..
Описаний нигде нет, разобраться можно только по исходникам и примерам применения. handle := hb_ProcessOpen( cCommand, [cStdIn], [@cStdOut], [@cStdErr], [lDetach] ) Здесь cCommand - сама команда, cStdIn - то, что для этой команды вы бы ввели с клавиатуры, cStdOut и cStdErr - в эти переменные записывается вывод запускаемой программы, если он направлен в стандартные потоки stdout, stderr, lDetach - чтобы запустить процесс и не ждать его завершения, "отвязать" от своей программы, @hProcess - сюда записывается идентификатор процесса. hb_ProcessClose() возвращает результат - удалось ли нормально завершить процесс.
|
|
|
|
| постоянный участник
|
Пост N: 7375
Зарегистрирован: 12.09.06
|
|
Отправлено: 18.05.23 11:24. Заголовок: alkresin пишет: hb_..
alkresin пишет: цитата: | hb_ProcessClose() возвращает результат - удалось ли нормально завершить процесс. |
| Это я понял, просто наверное nResult нужно поменять на lResult ! А то получается, что ожидаешь число (N), и пишешь сразу в коде HB_NtoS(nResult) и получаешь пустоту....
|
|
|
|
| moderator
|
Пост N: 1495
Зарегистрирован: 06.07.06
|
|
Отправлено: 18.05.23 12:48. Заголовок: А... Ну да, надо буд..
А... Ну да, надо будет исправить
|
|
|
|
| постоянный участник
|
Пост N: 7377
Зарегистрирован: 12.09.06
|
|
Отправлено: 18.05.23 13:55. Заголовок: Ещё вопрос по вашей ..
Ещё вопрос по вашей документации. Можно ли разместить отдельный пример работы с потоком с одной базой данных ? Не знаю как сделать у себя. Базу открываю монопольно, запускаются несколько потоков с РАЗНЫМИ RECNO(), нужно записать в базу по этим RECNO() что-то и потом завершить поток.
|
|
|
|
| moderator
|
Пост N: 1496
Зарегистрирован: 06.07.06
|
|
Отправлено: 18.05.23 15:45. Заголовок: Не получится. В доку..
Не получится. В документации написано, что workarea - локальные ресурсы потока, т.е., они не наследуются потоком. Для проверки написал вот это: Скрытый текст Function Main LOCAL hThread IF hb_mtvm() ? "Start" ELSE ? "No threads support..." QUIT ENDIF select a use life exclusive hThread := hb_threadStart( @thFunc() ) hb_threadDetach( hThread ) Inkey(1) ? "End" return nil Function thFunc select a dbgoto( 3 ) ? field->EVENT return nil
| и оно не работает, потому что поток "не видит" открытую родителем базу. Да, вообще говоря, такой режим работы не очень эффективен. Если бы это работало, то надо было бы расставлять мьютексы: hb_mutexLock( mutex1 ) dbgoto( nRec ) field->MYFIELD := ... hb_mutexUnLock( mutex1 ) чтобы между dbgoto() и изменением записи другой поток не передвинул указатель записи в другое место. Так что вряд ли это получится быстрее, чем в одном потоке.
|
|
|
|
| постоянный участник
|
Пост N: 7378
Зарегистрирован: 12.09.06
|
|
Отправлено: 18.05.23 16:46. Заголовок: Спасибо, понял ! :s..
Спасибо, понял ! А если открывать базу тогда в многопользовательском режиме ? Или вообще заново открывать базу в этом потоке, а потом закрывать. Будет тогда работать ? Мне не быстрота нужна, а независимость потока для записи в базу. Т.е. что то сделали в потоке и записали в базу. А в это время юзер может передвигаться по базе в основном потоке.
|
|
|
|
| moderator
|
Пост N: 1497
Зарегистрирован: 06.07.06
|
|
Отправлено: 18.05.23 19:52. Заголовок: Да, базу надо открыв..
Да, базу надо открывать в потоке в shared режиме, будет работать.
|
|
|
|
|
| постоянный участник
|
Пост N: 1640
Зарегистрирован: 27.01.07
|
|
Отправлено: 18.05.23 20:28. Заголовок: Andrey пишет: что т..
Andrey пишет: цитата: | что то сделали в потоке и записали в базу. А в это время юзер может передвигаться по базе в основном потоке |
| Нужно как-то отслеживать изменения. Иначе юзер может их и не увидеть.
|
|
|
|
| постоянный участник
|
Пост N: 7379
Зарегистрирован: 12.09.06
|
|
Отправлено: 18.05.23 20:58. Заголовок: PSP пишет: Нужно ка..
PSP пишет: цитата: | Нужно как-то отслеживать изменения. Иначе юзер может их и не увидеть. |
| Ну можно сделать Public nPubUpdateBase := 0 и из потока присваивать 1 при нужных условиях. А в главном потоке следить за этой переменной и делать Refresh базы если nPubUpdateBase == 1 Только как это реализовывать я не знаю ... Нужно как то блокировать переменную M->nPubUpdateBase ?
|
|
|
|
| |
Пост N: 1934
Зарегистрирован: 20.02.11
|
|
Отправлено: 19.05.23 08:10. Заголовок: Andrey пишет: Ну мо..
Andrey пишет: цитата: | Ну можно сделать Public nPubUpdateBase := 0 и из потока присваивать 1 при нужных условиях. |
| Поток используется чтобы не прерывать работу в основном процессе. Базы открываются в каждом потоке в режиме совместного доступа и логика точно такая же как и при работе с базой нескольких пользователей. Естественно в рамках работы в одной программе у нас есть вся информация о действиях "второго" пользователя и можно организовать хитрые рефреши если изменились записи из активного окна бровса, но на практике не заморачиваемся и все как при работе многопользовательской среде.. Если открывать базу в монопольном режиме, то eе нужно перемещать в zero space и забирать оттуда потоком при необходимости ( не забывая возвращать ) . Пока не забрали - алиас в потоке не увидим. У Александра все очень доступно написано о принципах работы с базой в многопоточке, никакие примеры не нужны. При монопольном доступе: Открыл базу и сразу в переместил в зеро. #xcommand UNLOCK WORKAREA [] => hb_dbDetach( ) #xcommand LOCK WORKAREA => hb_dbRequest( , .T.,, .T. ) При необходимости забрал из зеро, поработал и вернул. Вот и вся хитрость. При многопользовательском: Все тоже как будто работает ещё другой пользователь. Можно в разных потоках открывать с одним и тем же алиасом, все равно он будет локальный и виден только в потоке ( как и все прочие установки RDD ) Ранее в xharbour потоком наследовались не только паблик переменные но и рабочие области, это приводило к тому, что приходилось вешать мютексы и запоминать установки RDD в рабочей области для их корректного восстановления. Позже и считаю правильным, наследование рабочей области убрали.
|
|
|
|
| постоянный участник
|
Пост N: 7386
Зарегистрирован: 12.09.06
|
|
Отправлено: 29.05.23 21:32. Заголовок: В МиниГуи есть глоба..
В МиниГуи есть глобальные переменные: App.Cargo := oHmgData() (App.Cargo):nTimerSec := 5 (App.Cargo):aClose := {} (App.Cargo):cFileDbf := GetStartUpFolder() + "\test.dbf" (App.Cargo):cAlias := "MyTest" И ещё можно делать на окно контейнер с нужными переменными: DEFINE WINDOW wMain ; ..... This.Cargo := oHmgData() // for the window we create an object without variables (conditionally empty) This.Cargo:lRefresh := .F. nRecno := (cAls)->Lastrec() This.Cargo:oBrw := oBrw // положить объект TBROWSE на форму This.Cargo:aBrw := ARRAY(nRecno) AFILL( This.Cargo:aBrw, 0 ) Если я запускаю поток: hb_threadDetach( hb_threadStart( HB_THREAD_INHERIT_MEMVARS, @RunExternal(), aFile, oWnd ) ) То эти переменные доступны в потоке. Вопрос такой, если нужно записать в потоке допустим в oWnd:Cargo:aBrw[25] := hPid или This.Cargo:lRefresh := .T. или AADD( (App.Cargo):aClose , {хендл окна, hPid, } ) НУЖНО ли делать блокировку этих переменных ? Или лучше использовать обычные PUBLIC переменные ? Или делать через класс TThrData (доступ в потоках к переменным идет с блокировками) из МиниГуи ?
|
|
|
|
| постоянный участник
|
Пост N: 4280
Зарегистрирован: 17.02.12
|
|
Отправлено: 30.05.23 06:55. Заголовок: Andrey пишет НУЖНО л..
Andrey пишет цитата: | НУЖНО ли делать блокировку этих переменных ? |
| Делай так (только используй h_objects.prg, в нем THmgData и TThrData max совмещены) FUNCTION oThrData() RETURN TThrData():New() тогда App.Cargo := oThrData() (App.Cargo):nTimerSec := 5 (App.Cargo):aClose := {} (App.Cargo):cFileDbf := GetStartUpFolder() + "\test.dbf" (App.Cargo):cAlias := "MyTest" ... DEFINE WINDOW wMain ; ..... This.Cargo := oThrData() // for the window we create an object without variables (conditionally empty) This.Cargo:lRefresh := .F. nRecno := (cAls)->Lastrec() This.Cargo:oBrw := oBrw // положить объект TBROWSE на форму This.Cargo:aBrw := ARRAY(nRecno) AFILL( This.Cargo:aBrw, 0 ) тогда и к этим переменным App.Cargo, This.Cargo доступ будет с блокировками в потоках, не путать с oBrw := This.Cargo:oBrw, тут обычный доступ. Можно делать свою переменную для потоков PUBLIC oThread := oThrData() и работать в потоках через нее. Управлять окнами, тсб можно через сообщения окну (по уст. событиям)
|
|
|
|
| moderator
|
Пост N: 1509
Зарегистрирован: 06.07.06
|
|
Отправлено: 02.06.23 14:58. Заголовок: Обновил Harbour для ..
|
|
|
Новых ответов нет
, стр:
1
2
3
4
5
6
7
8
All
[см. все]
|
|