Форум: "Основная";
Текущий архив: 2004.10.03;
Скачать: [xml.tar.bz2];
ВнизПочему умирает иконка в трее? Найти похожие ветки
← →
guest_Dmitry (2004-09-08 19:21) [0]Программа читает данные из COM порта. После считывания выполняет ряд запросов к базе данных и возвращается в ожидание. В результате иконка в трее перестает реагировать на попытки открыть меню. В чем может быть причина этого? Использую RxTrayIcon.
← →
DiamondShark © (2004-09-08 21:32) [1]Потому что сообщения от иконки обрабатывает окно программы. А программа однопоточная.
← →
guest_Dmitry (2004-09-09 05:54) [2]Расскажите в двух словах как поправить это. Такая же программа, только выполняющая после чтения немного другие функции работает на ура.
← →
sniknik © (2004-09-09 09:04) [3]> Расскажите в двух словах как поправить это.
сделать 2 потока. (извини в 2-а слова не вложился, но почти...)
или прерывать твой бесконечный цикл (гдето есть такой) время от времени обработчиком событий (Application.ProcessMessages куда нужно вставить)
← →
guest_Dmitry (2004-09-10 11:52) [4]Попробовал вставить Application.ProcessMessages - не помогает.
В процедуре после чтения штрих кода у меня печатается несколько печатных форм FastReport. Убираешь печать - все работает нормально. Попробовал создать второй поток, который после выполнения процедуры убивался. Эффект умирания иконки ушел, но при попытке закрытия приложения получаю - "неверный дескриптор окна".
← →
guest_Dmitry (2004-09-14 16:27) [5]Может у кого-то все-таки есть соображения по этому вопросу? Неверный дескриптор окна получаю когда при закрытии формы уничтожаются компоненты на ней, к этому времени frReport уже оказывается разрушенным...
← →
Digitman © (2004-09-14 16:55) [6]
> Неверный дескриптор окна получаю когда при закрытии формы
> уничтожаются компоненты на ней, к этому времени frReport
> уже оказывается разрушенным
о боже ... каша какая-то ... формы, дескрипторы, рипорты какие-то ...
ты пойми, что для каждого трэда есть kernel-time и есть user-time
реакция на вин-сообщения требует kernel-time, и если некий тред в некий момент времени находится в user-time, то он (трэд) все это время никак не в состоянии реагировать на GUI-события/сообщения !
← →
guest_Dmitry (2004-09-14 17:14) [7]гм... в треде идет ожидание данных из порта. в это время форма прекрасно реагирует на вин-сообщения (я так понимаю на то тред и нужен). после получения данных выполняется ряд запросов к базе данных - все отрабатывает без проблем. возвращаюсь к ожиданию, все вин-сообщения ловятся. только начинаю работать с репортом - начинаются проблемы.
← →
guest_Dmitry (2004-09-14 18:26) [8]Вот полностью работающий код. За основу был взят код из статьи с этого сайта "Работа с COM портами под Windows"
unit PortUnit;
interface
uses windows, sysutils, dialogs, forms, Messages, classes;
var
CommHandle : integer;
DCB : TDCB;
Ovr : TOverlapped;
Stat : TComStat;
CommThread : THandle;
hEvent : THandle;
Flag,StopResive : boolean;
KolByte,Kols,Mask,TransMask,Errs : DWord;
doc_id: integer;
s: string;
procedure PortInit;
procedure ReadComm;
procedure KillComm;
procedure SetMark;
procedure mybeep(Tone: Word; Delay: Integer);
implementation
uses
Main, StdCtrls, uDM;
procedure KillComm;
begin
TerminateThread(CommThread,0);
CloseHandle(CommHandle);
end;
procedure ReadComm;
var thread: TSimpleThread;
begin
while true do
begin
TransMask:=0;
WaitCommEvent(CommHandle,TransMask,nil);
if (TransMask and EV_RXFLAG)=EV_RXFLAG then
begin
s := "";
ClearCommError(CommHandle,Errs,@Stat);
Kols := Stat.cbInQue;
SetLength(s, kols);
ReadFile(CommHandle,s[1],Kols,Kols,@ovr);
PurgeComm(CommHandle, PURGE_RXCLEAR);
s := string(s);
s := trim(s);
try
doc_id := StrToInt(s);
SetMark;
except
ShowMessage("Â êîäå äîëæåí ñîäåðæàòüñÿ ID äîêóìåíòà");
end;
end;
end;
end;
procedure PortInit;
var
ThreadID:dword;
begin
doc_id := 0;
CommHandle := CreateFile(pchar(Form1.Edit2.Text),GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,0);
SetCommMask(CommHandle,EV_RXFLAG);
GetCommState(CommHandle,DCB);
DCB.BaudRate:=CBR_9600;
DCB.Parity:=NOPARITY;
DCB.ByteSize:=8;
DCB.StopBits:=OneStopBit;
DCB.EvtChar:=chr(13);
SetCommState(CommHandle,DCB);
CommThread := CreateThread(nil,0,@ReadComm,nil,0,ThreadID);
end;
procedure SetMark;
begin
Form1.pFIBQuery1.Close;
Form1.pFIBQuery1.SQL.Text := "select id from documents where rowcount > 0 and id ="+IntToStr(doc_id);
Form1.pFIBQuery1.ExecQuery;
if Form1.pFIBQuery1.FieldByName["id"].AsInteger <> doc_id
then begin
ShowMessage("Äàííîãî äîêóìåíòà íåò â áàçå äàííûõ");
doc_id := 0;
Form1.pFIBQuery1.Close;
exit;
end;
Form1.pFIBQuery1.Close;
Form1.pFIBQuery1.SQL.Text := "select z(mark0)+z(mark3) as marks from documents where id ="+IntToStr(doc_id);
Form1.pFIBQuery1.ExecQuery;
if Form1.pFIBQuery1.FieldByName["marks"].AsInteger <> 1
then begin
if Form1.pFIBQuery1.FieldByName["marks"].AsInteger = 0 then
ShowMessage("Íåò ïåðâîé îòìåòêè íà äîêóìåíòå");
if Form1.pFIBQuery1.FieldByName["marks"].AsInteger = 2 then
ShowMessage("Îòìåòêà íà äîêóìåíò óæå ïîñòàâëåíà");
doc_id := 0;
Form1.pFIBQuery1.Close;
exit;
end;
Form1.pFIBQuery1.Close;
Form1.pFIBQuery1.SQL.Text := "update v_docmarks set mark3 = 1 where id ="+IntToStr(doc_id);
Form1.pFIBQuery1.ExecQuery;
Form1.pFIBTransaction1.CommitRetaining;
Form1.pFIBQuery1.Close;
doc_id := 0;
end;
end.
Только в процедуру SetMark добавляешь
Form1.frReport1.LoadFromFile(Form1.Edit3.Text+Form1.pFIBQuery1.FieldByName["frf"].AsString);
Form1.frReport1.PrepareReport;
начинаются проблемы.
← →
simpson © (2004-09-14 18:33) [9]> guest_Dmitry (14.09.04 18:26) [8]
> За основу был взят код из статьи с этого сайта "Работа с COM
> портами под Windows"
Не читай ее. Это - малограмотный бред сивой кобылы.
← →
guest_Dmitry (2004-09-14 18:37) [10]>simpson © (14.09.04 18:33) [9]
я же говорю "за основу".
почитал еще статьи, подправил немного - работает вроде без глюков.
хотелось бы по сабжу...
← →
simpson © (2004-09-14 18:41) [11]ага... особенно вот это:
procedure KillComm;
begin
TerminateThread(CommThread,0);
CloseHandle(CommHandle);
end;
это:WaitCommEvent(CommHandle,TransMask,nil);
и это:
ShowMessage("Â êîäå äîëæåí ñîäåðæàòüñÿ ID äîêóìåíòà");
Уж как минимум, эти "ляпы" делают этот код не нормальным...
← →
simpson © (2004-09-14 18:44) [12]Тут сегодня уже объясняли одному товарищу, почему нельзя вызывать ShowMessage из другого потока просто так.
Сходи сюда:
http://delphimaster.net/view/1-1095161831/
← →
guest_Dmitry (2004-09-14 18:49) [13]ShowMessage то я уберу, проблема то от этого не решится....
← →
simpson © (2004-09-14 18:57) [14]Уважаемый, цитирую Вас: "Вот полностью работающий код".
Отвечаю: ложь. Он не работающий. В нем море ошибок. Я не просто обращаю внимание на вызов ShowMessage: SetMark так же вызывается из дополнительного потока. В нем тоже есть вызовы ShowMessage. И вызов Form1.frReport1.PrepareReport.
Та вот, эти вызовы потоконебезопасны. Прочитайте про это понятие в справке - и решите проблему. Примите за аксиому: нельзя из дополнительного потока просто так обращаться к визуальным компонентам VCL.
Кроме того, код работающий с COM-портом - мягко говоря, некорректный.
← →
guest_Dmitry (2004-09-14 19:06) [15]Каким образом тогда обращаться к визуальным компонентам, если это все-таки необходимо?
← →
simpson © (2004-09-14 19:08) [16]Например, использовать класс TThread - у него есть метод Synchronize, с помощью которого можно производить такие действия. Еще вариант - посылать сообщения окну через PostMessage.
← →
simpson © (2004-09-14 19:12) [17]Кстати, если слова про "код работающий с COM-портом - мягко говоря, некорректный" не вдохновляют, в качестве примера приведу цитату из самого правильного сборника статей по программированию для Windows - MSDN:
TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
If the target thread owns a critical section, the critical section will not be released.
If the target thread is allocating memory from the heap, the heap lock will not be released.
If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread"s process could be inconsistent.
If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
← →
guest_Dmitry (2004-09-14 19:18) [18]Т.е. я так понял создавать еще однин поток и все действия производить в TMyThread.Execute? Пробовал я делать и так, прочитав [3]. В результате при закрытии главной формы приложения получаю "Неверный дескриптор окна" - вызывается метод destroy уже разрушеного компонента frreport.
← →
simpson © (2004-09-14 19:22) [19]> guest_Dmitry (14.09.04 19:18) [18]
> Пробовал я делать и так, прочитав [3]
Э... т. е. добавил вызов "Application.ProcessMessages" в теле метода Execute? А нафига?
Не, срочно читаем Рихтера.
← →
guest_Dmitry (2004-09-14 19:29) [20]Почему? В TMyThread.Execute поместил код из процедуры SetMark
и вместо ее вызова использовал
thread := TMyThread.Create(false);
← →
simpson © (2004-09-14 19:34) [21]Хм... сдается, что понимание смысла использования дополнительных поток отсутствует...
Общий алгоритм:
1. Создаещь потомка TThread (это обертка вокруг thread, с которым в твоем примере ты работешь с пом. API-функций).
2. В его Execute (это - собственно поток) ожидаешь данные из порта.
3. Как только данные пришли, вызываешь Synchronize, которому передаешь указатель на метод, в котором, в свою очередь, делаешь все, что тебе надо с визуальщиной.
Двух потоков не создавать не надо.
← →
simpson © (2004-09-14 19:37) [22]> simpson © (14.09.04 19:34) [21]
> использования дополнительных поток отсутствует
дополнительных потоков
← →
guest_Dmitry (2004-09-14 19:44) [23]Вроде более-менее понятно... Буду пробовать.
Если статья на этом сайте по работе с com портами некорректна, что можно прочитать по данному вопросу? вот еще нашел статью, в ней вроде описанных ляпов не обнаружено -
http://z-oleg.com/delphi/hardw5.htm
← →
guest_Dmitry (2004-09-15 13:46) [24]>simpson © (14.09.04 19:34) [21]
Спасибо! Разобрался, все заработало.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.10.03;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.036 c