Форум: "WinAPI";
Текущий архив: 2007.03.11;
Скачать: [xml.tar.bz2];
ВнизProcessMessages Найти похожие ветки
← →
dmirror (2006-10-31 14:08) [0]В чистом приложении вызов Application.processmessages работает.
Создаю поток
type
TServiceThread = class(TThread)
public
procedure Execute; override;
end;
---
var
ServiceThread: TServiceThread;
и на processmessages компилятор начинает ругаться что не видит такой функции.
что может быть и как исправить?
← →
Eraser © (2006-10-31 14:13) [1]> [0] dmirror (31.10.06 14:08)
> и на processmessages компилятор начинает ругаться что не
> видит такой функции.
код показываей, где ругается.
ЗЫ
не вздумай вызывать processmessages из доп. потока.
← →
Сергей М. © (2006-10-31 14:14) [2]processmessages - это не функция, а процедурный метод объекта класса TApplication.
← →
YuRock © (2006-10-31 15:55) [3]
> Eraser © (31.10.06 14:13) [1]
>
> ЗЫ
> не вздумай вызывать processmessages из доп. потока.
>
Почему?
← →
Ketmar © (2006-10-31 16:02) [4]>[3] YuRock(c) 31-Oct-2006, 15:55
>Почему?
поверь на слово пока. ибо это с 1917 года надо про шпингалеты пояснять.
← →
YuRock © (2006-10-31 16:05) [5]
> поверь на слово пока. ибо это с 1917 года надо про шпингалеты
> пояснять.
Хорошо. Я тогда тоже дам совет. Не пользуйся никогда компонентом TButton. Почему? Поверь на слово - я знаю, почему...
← →
Ketmar © (2006-10-31 16:10) [6]>[5] YuRock(c) 31-Oct-2006, 16:05
ещё один надмозг. сезон, что ли? игнор.
← →
Eraser © (2006-10-31 16:13) [7]> [3] YuRock © (31.10.06 15:55)
> Почему?
Зачем?
Зачем понадобилось вызывать ProcessMessages в доп. потоке?
Нельзя вызывать, потому что ProcessMessages позволяет перейти к обработке всей очереди сообщений основного потока приложения, тем самым прервав выполнение кода в основном же потоке, до тех пор, пока метод ProcessMessages не выполнится.
Если вызвать ProcessMessages из доп. потока, то программа или этот поток, в лучшем случае, скорее всего подвиснут.
← →
Сергей М. © (2006-10-31 16:17) [8]
> YuRock © (31.10.06 15:55) [3]
> Почему?
Дурацкий вопрос.
Ну, если желаешь ответ на него, то хотя бы потому что поле TApplication.FTerminate не защищено крит.секцией. И при этом нет никаких гарантий, что потоку не послано WM_QUIT.
Смотреть и изучать исходники класса TApplication до полного просветления)
← →
Игорь Шевченко © (2006-10-31 16:44) [9]Eraser © (31.10.06 16:13) [7]
> Нельзя вызывать, потому что ProcessMessages позволяет перейти
> к обработке всей очереди сообщений основного потока приложения,
> тем самым прервав выполнение кода в основном же потоке,
> до тех пор, пока метод ProcessMessages не выполнится.
С этого момента подробнее - каким образом ProcessMessages вызыванный из неосновного потока позволяет перейти к обработке всей очереди сообщений основного потока приложения.
← →
Eraser © (2006-10-31 16:47) [10]> [9] Игорь Шевченко © (31.10.06 16:44)
в том то и дело что никаким.
← →
YuRock © (2006-10-31 17:07) [11]> Ketmar c (31.10.06 16:10) [6]
> Eraser c (31.10.06 16:13) [7]
> Сергей М. c (31.10.06 16:17) [8]
Пасиба, олбанский выучил!
> dmirror (31.10.06 14:08)
Поменьше слушай голословные советы умников на форумах, побольше - читай хелп и смотри исходники.
TApplication.ProcessMessages вполне допустимо для выкрутки сообщений любого потока. Ведь это простой цикл PeekMessage. Единственное, с чем может случиться заморочка - это со свойством OnMessage у TApplication. Если оно присвоено - то будет вызываться из того потока, откуда вызвано ProcessMessages. И тут уже все зависит от того, что за код там написан. Если этого свойства нет - проблем быть не может.
Другой вопрос - зачем вызывать ProcessMessages? Оно удобно для того, чтобы выкрутить накопившуюся очередь. Принудительно.
Но не предназначено для ожидания и выкрутки сообщений, тут надо использовать цикл GetMessage.
Ниже пример с использованием Application.ProcessMessages в другом потоке. Все работает великолепно - только
неправильно логически - "оно" для другого надо. И из-за этого 100% проца жрется. Да и далеко не все сообщения "оно" обрабатывает.
Так что если этот цикл закомментить и раскомментить следующий - будет намного лучше.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TTestThread = class( TThread )
protected
procedure Execute; override;
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
FTread: TTestThread;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function TestThreadWndProc( hWindow: HWND; msg: Cardinal; wParam: WPARAM; lParam: LPARAM ): Integer; stdcall;
begin
Result := DefWindowProc( hWindow, msg, wParam, lParam );
end;
procedure TTestThread.Execute;
var
hWindow: HWND;
Msg: TMSG;
begin
hWindow := CreateWindow( "___TestThreadWndClass", "Îêíî èç äðóãîãî ïîòîêà ( Îáðàáàòûâàåòñ&# 255; Application.ProcessMessages )", WS_VISIBLE or WS_SIZEBOX or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX, 100, 100, 600, 200, 0, 0, hInstance, nil );
while not Terminated do
Application.ProcessMessages;
{while not Terminated and GetMessage( Msg, 0, 0, 0 ) do begin
TranslateMessage( Msg );
DispatchMessage( Msg );
end;}
DestroyWindow( hWindow );
end;
procedure TForm1.FormCreate(Sender: TObject);
var
wc: WNDCLASS;
begin
FillChar( wc, sizeof( WNDCLASS ), 0 );
wc.lpfnWndProc := @TestThreadWndProc;
wc.hInstance := hInstance;
wc.hCursor := LoadCursor( 0, IDC_ARROW );
wc.lpszClassName := "___TestThreadWndClass";
wc.hbrBackground := CreateSolidBrush( GetSysColor( COLOR_BTNFACE ) );
Windows.RegisterClass( wc );
FTread := TTestThread.Create( True );
with FTread do begin
FreeOnTerminate := True;
Resume;
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FTread.Terminate;
end;
end.
← →
Eraser © (2006-10-31 17:17) [12]> [11] YuRock © (31.10.06 17:07)
> Пасиба, олбанский выучил!
учи еще.
только потом не удивляйся, что приложение будет "вываливаться" с AV в самых неожиданных местах.
> Да и далеко не все сообщения "оно" обрабатывает.
это с каких пор?
← →
YuRock © (2006-10-31 17:21) [13]> Eraser © (31.10.06 17:17) [12]
1. Йа пастаянна учу, пасиба исчо рас! Да, приложения, написанные мной, работают месяцами, пока винда не сдохнет.
2. С тех пор, как борланд так реализовал этот метод. Как минимум с D6 - более старых версий у меня нет под рукой.
← →
Игорь Шевченко © (2006-10-31 17:22) [14]Eraser © (31.10.06 16:47) [10]
> Нельзя вызывать, потому что ProcessMessages позволяет перейти
> к обработке всей очереди сообщений основного потока приложения,
> тем самым прервав выполнение кода в основном же потоке,
> до тех пор, пока метод ProcessMessages не выполнится.
> Если вызвать ProcessMessages из доп. потока, то программа
> или этот поток, в лучшем случае, скорее всего подвиснут.
>
> в том то и дело что никаким.
Вот две твоих цитаты. Ты их связать можешь ? А то у меня не получается.
← →
@!!ex © (2006-10-31 17:46) [15]А я почемуто всегда думал, что ProcessMessages нужно для того чтобы прервать текущее действие основного потока и обработать мессаги....
Вопрос: зачем из стороннего потока вызывать обработку сообщений главного потока?
Ответ: Чтобы напороться на AV.
← →
YuRock © (2006-10-31 17:48) [16]
> @!!ex © (31.10.06 17:46) [15]
> Вопрос: зачем из стороннего потока
> вызывать обработку сообщений главного потока?Ответ: Чтобы
> напороться на AV.
:))))))))))))))))))))))))))))))))))))))))))))))
← →
Eraser © (2006-10-31 17:57) [17]> [14] Игорь Шевченко © (31.10.06 17:22)
криво мысль изложил ) согласен.
надо было уточнить, что вызывать ProcessMessages следует из осн. потока.
> зачем из стороннего потока вызывать обработку сообщений
> главного потока?
именно это сделать нельзя. можно только если вызов обернуть в Synchronize.
← →
YuRock © (2006-10-31 18:00) [18]Я извиняюсь перед админами форума, просто нервы - ни к черту...
Через пару часов на стадион идти - Шахтер-Валенсия - и меня колбаси не по детски... Делать ничего не могу.
Орешник уже перечитал полностью. Оценил :)
Но мало. А, как оказалось, обсуждения обычных вопросов, споры и советы специалистов тут не хуже орехов :)
Так что еще раз прошу прощения и понимания. Кстати, надеюсь, какую-то пользу автору темы, к-рый задавал вопрос, я все же принес. Так что это смягчающее обстоятельство ;)
← →
Игорь Шевченко © (2006-10-31 18:09) [19]Eraser © (31.10.06 17:57) [17]
> надо было уточнить, что вызывать ProcessMessages следует
> из осн. потока.
Почему ?
← →
Eraser © (2006-10-31 18:13) [20]> [19] Игорь Шевченко © (31.10.06 18:09)
потому что borland не рекомендует вызывать методы VCL объектов из доп. потока.
← →
YuRock © (2006-10-31 18:14) [21]> Игорь Шевченко © (31.10.06 18:09) [19]
> Почему ?
Я уже задавал этот вопрос - [3].
Поступило около 15 ответов - неужели Вам не достаточно? :)
← →
@!!ex © (2006-10-31 18:16) [22]
> 1. Йа пастаянна учу, пасиба исчо рас! Да, приложения, написанные
> мной, работают месяцами, пока винда не сдохнет.
Винда дохнет из-за ваших приложений? ;)
> Игорь Шевченко © (31.10.06 18:09) [19]
Теоретически может привести к AB в ОЧЕНЬ редких случаях как уже было сказано в > Сергей М. © (31.10.06 16:17) [8] .
Мьютекс на FTerminate...
ТОка это всего лишь один из вариантов, которые могут привести к AV.
← →
Игорь Шевченко © (2006-10-31 18:21) [23]Eraser © (31.10.06 18:13) [20]
> потому что borland не рекомендует вызывать методы VCL объектов
> из доп. потока.
Все методы всех объектов ?
← →
Eraser © (2006-10-31 18:22) [24]> [21] YuRock © (31.10.06 18:14)
вот код метода ProcessMessage, который вызывается в цикле из ProcessMessages.function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
var
Unicode: Boolean;
Handled: Boolean;
MsgExists: Boolean;
begin
Result := False;
if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
begin
Unicode := (Msg.hwnd <> 0) and IsWindowUnicode(Msg.hwnd);
if Unicode then
MsgExists := PeekMessageW(Msg, 0, 0, 0, PM_REMOVE)
else
MsgExists := PeekMessage(Msg, 0, 0, 0, PM_REMOVE);
if not MsgExists then Exit;
Result := True;
if Msg.Message <> WM_QUIT then
begin
Handled := False;
if Assigned(FOnMessage) then FOnMessage(Msg, Handled); // может привести к серьезным проблемам,
// если этот обработчик расчитан для работы в осн. потоке.
if not IsPreProcessMessage(Msg) and not IsHintMsg(Msg) and // есть подозрение, что эти методы тоже не потоко-безопасны.
not Handled and not IsMDIMsg(Msg) and // тут вообще код лезет к объекту TScreen...
not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
begin
TranslateMessage(Msg);
if Unicode then
DispatchMessageW(Msg)
else
DispatchMessage(Msg);
end;
end
else
FTerminate := True; // про это сказано в [8].
end;
end;
← →
Eraser © (2006-10-31 18:25) [25]> [23] Игорь Шевченко © (31.10.06 18:21)
не всех конечно, но всех визуальных объектов. не визуальные, чаще всего (но не всегда) можно использовать не только в гл. потоке, но и в доп., но желательно только в том, где данный объект и был создан.
← →
YuRock © (2006-10-31 18:37) [26]> if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
> // может привести к серьезным проблемам,
> // если этот обработчик расчитан для работы в осн. потоке.
А может и не привести. Все зависит от того, что за код программист написал в OnMessage. И вообще - написал ли. Я этот момент упомянул в [11].
> // есть подозрение, что эти методы тоже не потоко-безопасны.
Они вполне безопасны. В них используются только элементарные функции WinApi - и нечего более.
> FTerminate := True; // про это сказано в [8].
Ну и что там сказано про это? Читаем: "поле TApplication.FTerminate не защищено крит.секцией. И при этом нет никаких гарантий, что потоку не послано WM_QUIT."
Что из этого? Ну послано - отлично! Присвоется эта переменная - так она и должна была присвоиться. НИЧЕГО страшного в этом нет.
← →
Eraser © (2006-10-31 18:45) [27]> [26] YuRock © (31.10.06 18:37)
> Они вполне безопасны. В них используются только элементарные
> функции WinApi - и нечего более.
уверен?
CancelHint к примеру? или ObjectFromHWnd? а в IsMDIMsg прямо вся состоит из вызова API? )
← →
Eraser © (2006-10-31 18:52) [28]> [26] YuRock © (31.10.06 18:37)
> Что из этого? Ну послано - отлично! Присвоется эта переменная
> - так она и должна была присвоиться. НИЧЕГО страшного в
> этом нет.
таки слона то мы все и не приметели )) как только доп. потоку будет послано WM_QUIT - приложение завершиться )
← →
YuRock © (2006-10-31 19:02) [29]
> уверен?CancelHint к примеру? или ObjectFromHWnd? а в IsMDIMsg
> прямо вся состоит из вызова API? )
Уверен на 100%. К этой строке выполнение может дойти только тогда, когда в потоке созданы VCL-ные хинты. А в дополнительных потоках их создать и работать с ними если не невозможно, то довольно сложно, как и с любыми VCL-объектами.
А IsMDIMsg, да, состоит вся из вызова API.
> таки слона то мы все и не приметели )) как только доп. потоку
> будет послано WM_QUIT - приложение завершиться )
Да, должно завершиться. Ну и? А в чем еще смысл посылки WM_QUIT? Обычно для этого как раз...
P.S. Все, спасибо всем за положительные эмоции - пора выдвигаться на стадио :)
← →
Eraser © (2006-10-31 19:17) [30]> [29] YuRock © (31.10.06 19:02)
> А IsMDIMsg, да, состоит вся из вызова API.
и чтения свойств визуальных VCL объектов.
при завершении приложения, если доп. поток еще будет ативен, в этом месте AV обязательно вылетит.function TApplication.IsMDIMsg(var Msg: TMsg): Boolean;
begin
Result := False;
if (MainForm <> nil) and (MainForm.FormStyle = fsMDIForm) and
(Screen.ActiveForm <> nil) and (Screen.ActiveForm.FormStyle = fsMDIChild) then
Result := TranslateMDISysAccel(MainForm.ClientHandle, Msg);
end;
> Да, должно завершиться.
это еще с какого перепугу? обычно (не заню как там у вас) WM_QUIT служит для завершения потока, а т.к. поток не основоной, зачем закрывать программу, да еще и через задний проход?
не слишкол ли много "если" надо учесть, чтобы код работал как надо?
по-моемуwhile not Terminated and GetMessage(Msg, 0, 0, 0) do begin
TranslateMessage( Msg );
DispatchMessage( Msg );
end;
гораздо проще и безопаснее.
← →
@!!ex © (2006-10-31 20:46) [31]
> YuRock
ощущени, что вы с потоками не работали....
В курсе, что будет если к одной переменной одновременно обратяться из двух разных потоков?
Семафоры и мьютексы не просто так придумали.
← →
Дмитрий Белькевич © (2006-11-01 02:44) [32]Господа, вам в жизни проблем мало, что бы еще и на эти грабли наступать - в appllication.processmessage может случится многое - нажатия на кнопки, перерисовка итд. И коматоз обеспечен.
← →
Игорь Шевченко © (2006-11-01 10:53) [33]Eraser © (31.10.06 19:17) [30]
> if (MainForm <> nil) and (MainForm.FormStyle = fsMDIForm)
property FormStyle: TFormStyle read FFormStyle
property ActiveForm: TForm read FActiveForm;
И чего ?
> при завершении приложения, если доп. поток еще будет ативен,
> в этом месте AV обязательно вылетит.
Пример не затруднит ?
← →
dmirror (2006-11-01 11:58) [34]ProcessMessagess запускается в основной программе а не в потоке, в потоке обслуживается генераторно-осцилографическая часть. А ProcessMessagess нужен для отслеживания событий системы позиционирования, просто без него не могу получить сигнал готовности.
Код слующий
procedure TForm1.ScanStartClick(Sender: TObject);
var
i,j : integer;
sx,sy,vx,vy : string;
uclen, k,h : integer;
temp : real;
begin
vx := Edit16.Text;
vy := Edit17.Text;
sx := Edit18.Text;
sy := Edit19.Text;
Stringcounter :=1;
IsFastScan:=true;
cRecBufSizeMaxF:=trunc(cSamplPS*StrToInt(sx)/StrToInt(vx));
cRecBufSizeMaxFBin:=(cRecBufSizeMaxF - (cRecBufSizeMaxF mod 2))*2;
for i:=1 to StrToInt(numlines.Text) do
begin
sleep(200);
isReady :=false;
cport.WriteStr("@0A 0,5000,"+sy+","+vy+#13#10);
start;
j:=0;
repeat
inc(j);
application.ProcessMessages();
until IsReady;{ or (j>=15);
if (j>=15) then begin
ShowMessage("Каретка не дошла до конца");
end; }
sleep(200);
isReady :=false;
Cport.WriteStr("@0A 0,5000,"+"-"+sy+","+vy+#13#10);
repeat
application.ProcessMessages();
until isReady = true;
sleep(200);
isReady :=false;
Cport.WriteStr("@0A"+sx+","+vx+",0,5000"+#13#10);
repeat
stringcounter:=Stringcounter+1;
application.ProcessMessages();
until isReady;
end;
IsFastScan:=false;
end;
А ларчик открывался достаточно просто - нужно было убить библиотеку svcmgr. После чего ProcessMessages заработал. А вот первопричина не понятна, в чистом приложении без потоков даже с svcmgr код работал
Всем спасибо!
← →
dmirror (2006-11-01 11:58) [35]ProcessMessagess запускается в основной программе а не в потоке, в потоке обслуживается генераторно-осцилографическая часть. А ProcessMessagess нужен для отслеживания событий системы позиционирования, просто без него не могу получить сигнал готовности.
Код слующий
procedure TForm1.ScanStartClick(Sender: TObject);
var
i,j : integer;
sx,sy,vx,vy : string;
uclen, k,h : integer;
temp : real;
begin
vx := Edit16.Text;
vy := Edit17.Text;
sx := Edit18.Text;
sy := Edit19.Text;
Stringcounter :=1;
IsFastScan:=true;
cRecBufSizeMaxF:=trunc(cSamplPS*StrToInt(sx)/StrToInt(vx));
cRecBufSizeMaxFBin:=(cRecBufSizeMaxF - (cRecBufSizeMaxF mod 2))*2;
for i:=1 to StrToInt(numlines.Text) do
begin
sleep(200);
isReady :=false;
cport.WriteStr("@0A 0,5000,"+sy+","+vy+#13#10);
start;
j:=0;
repeat
inc(j);
application.ProcessMessages();
until IsReady;{ or (j>=15);
if (j>=15) then begin
ShowMessage("Каретка не дошла до конца");
end; }
sleep(200);
isReady :=false;
Cport.WriteStr("@0A 0,5000,"+"-"+sy+","+vy+#13#10);
repeat
application.ProcessMessages();
until isReady = true;
sleep(200);
isReady :=false;
Cport.WriteStr("@0A"+sx+","+vx+",0,5000"+#13#10);
repeat
stringcounter:=Stringcounter+1;
application.ProcessMessages();
until isReady;
end;
IsFastScan:=false;
end;
А ларчик открывался достаточно просто - нужно было убить библиотеку svcmgr. После чего ProcessMessages заработал. А вот первопричина не понятна, в чистом приложении без потоков даже с svcmgr код работал
Всем спасибо!
← →
Сергей М. © (2006-11-01 13:30) [36]
> нужно было убить библиотеку svcmgr
А как она у тебя оказалась в проекте обычного GUI-приложения ?
← →
YuRock © (2006-11-01 15:17) [37]
> ощущени, что вы с потоками не работали....В курсе, что будет
> если к одной переменной одновременно обратяться из двух
> разных потоков?Семафоры и мьютексы не просто так придумали.
>
Да, знаю. В худшем случае - логические ошибки. Которые, конечно, могут повлечь за собой все, что угодно. А могут и не повлечь, как в случае с безобидным сравнение двух чисел:if (MainForm <> nil) and (MainForm.FormStyle = fsMDIForm)
← →
Eraser © (2006-11-01 15:20) [38]> [33] Игорь Шевченко © (01.11.06 10:53)
мда.. насчет AV в (MainForm <> nil) and (MainForm.FormStyle = fsMDIForm) эт я погорячился, не учел тот факт, что форма не уничтожается, когда заканчивается Run. Но сути дела это не меняет. Я б не стал использовать методы TApplication для обработки сообщений в доп. потоке.
← →
Anatoly Podgoretsky © (2006-11-01 15:23) [39]> Eraser (01.11.2006 15:20:38) [38]
> (MainForm <> nil) and (MainForm.FormStyle = fsMDIForm)
С потоками, я бы не назвал это код безобидным, легко получить как минимум AV
Это не атомарная операция.
← →
Eraser © (2006-11-01 15:24) [40]> [37] YuRock © (01.11.06 15:17)
> (MainForm <> nil) and (MainForm.FormStyle = fsMDIForm)
кстати подобных конструкций тоже стараюсь избегать.. в отличие от борланада ) хотя они если и поменяют работу компилятора - первые об этом узнают и перепишут код, а вот мне искать внезапно-появившиеся ошибки, при переходе на новую версию компилятора, в проекте на несколько десятков тысяч строк не хочется.
Страницы: 1 2 3 вся ветка
Форум: "WinAPI";
Текущий архив: 2007.03.11;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.116 c