Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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)

кстати подобных конструкций тоже стараюсь избегать.. в отличие от борланада ) хотя они если и поменяют работу компилятора - первые об этом узнают и перепишут код, а вот мне искать внезапно-появившиеся ошибки, при переходе на новую версию компилятора, в проекте на несколько десятков тысяч строк не хочется.


 
Eraser ©   (2006-11-01 15:25) [41]

> [39] Anatoly Podgoretsky ©   (01.11.06 15:23)

ну записи то там нет.


 
Anatoly Podgoretsky ©   (2006-11-01 15:45) [42]

> Eraser  (01.11.2006 15:24:40)  [40]

Да код не безобидный даже и без потоков, легко получить не то что задумал.
Но это уже много раз разжевывалось.


 
Anatoly Podgoretsky ©   (2006-11-01 15:47) [43]

> Eraser  (01.11.2006 15:25:41)  [41]

За то есть обращение к непринадлежащей тебе памяти. Между первой и второй
перерывчик не большой, во время которого второй поток уже уничтожил объект -
тут нужна критическая секция.


 
YuRock ©   (2006-11-01 16:08) [44]


> Anatoly Podgoretsky ©   (01.11.06 15:47) [43]
> За то есть обращение
> к непринадлежащей тебе памяти. Между первой и второйперерывчик
> не большой, во время которого второй поток уже уничтожил
> объект -тут нужна критическая секция.


Блин, а голова программеру на что? Естественно, что пользоваться средствами, предоставленными Борландом, Майкрософтом и т.д. надо с умом! В этом случае, например, если используешь Application.ProcessMessages для выкрутки сообщений другого потока, надо знать, что желательно поток-то этот закрыть вообще нафиг, перед тем, как MainForm уничтожится (если она была вообще, конечно).


> Eraser ©   (01.11.06 15:24) [40]
> (MainForm.FormStyle = fsMDIForm)кстати подобных конструкций
> тоже стараюсь избегать.. в отличие от борланада ) хотя они
> если и поменяют работу компилятора - первые об этом узнают
> и перепишут код, а вот мне искать внезапно-появившиеся ошибки,
>  при переходе на новую версию компилятора, в проекте на
> несколько десятков тысяч строк не хочется.


А с этим кодом что плохого? И при чем тут компилятор?


 
Anatoly Podgoretsky ©   (2006-11-01 16:21) [45]

> YuRock  (01.11.2006 16:08:44)  [44]

> а голова программеру на что

А ты много такого видел, откуда тогда берутся AV?


 
YuRock ©   (2006-11-01 16:26) [46]


> А ты много такого видел, откуда тогда берутся AV?


Нет, немного. Я видел только один случай, откуда берутся AV: когда обращаются к адресу памяти, доступа к которому нет.


 
Anatoly Podgoretsky ©   (2006-11-01 16:51) [47]

> YuRock  (01.11.2006 16:26:46)  [46]

Например между первой и второй перерывчик небольшой.


 
@!!ex ©   (2006-11-01 16:58) [48]


> YuRock ©   (01.11.06 16:26) [46]

Собственно никто не обещает, что при проверке второй части условия форма все еще будет не Nil. :))


 
Anatoly Podgoretsky ©   (2006-11-01 17:04) [49]

> @!!ex  (01.11.2006 16:58:48)  [48]

Это первая проблема, а вторая никто не гарантирую, что не будут вычисляться
обе части выражения, первая безопасная, а по второй имеется счастье получить
AV по полной программе. Зависит от настроек компилятора.
Помню как кто то очень громко ругался на форумах :-)


 
Игорь Шевченко ©   (2006-11-01 17:06) [50]

@!!ex ©   (01.11.06 16:58) [48]


> Собственно никто не обещает, что при проверке второй части
> условия форма все еще будет не Nil. :))


А собственно, посмотреть, при каких условиях она станет nil при проверке второго условия ?


 
@!!ex ©   (2006-11-01 17:13) [51]


> Игорь Шевченко ©   (01.11.06 17:06) [50]

Если поток на некоторое время зависинит(ОС не гарантирует что всем потокам выделяется абсолютно одинаковое количество процессорного времени) и за это время форма будет уничтожена.


 
Eraser ©   (2006-11-01 17:20) [52]

> [44] YuRock ©   (01.11.06 16:08)


> Блин, а голова программеру на что? Естественно, что пользоваться
> средствами, предоставленными Борландом, Майкрософтом и т.д.
> надо с умом!

за такое "с умом" с работы попереть могут. я бы призадумался о компетенции такого работника.
учти, что даже если тебе полностью понятно, как работает этот код в текущей версии VCL, человек, который возможно в будущем будет заниматься поддержкой/развитием данного кода может быть не в курсе тонкостей.


 
Игорь Шевченко ©   (2006-11-01 17:30) [53]

@!!ex ©   (01.11.06 17:13) [51]

Который из потоков ? :)


 
@!!ex ©   (2006-11-01 17:46) [54]

Зависнет поток в котором выполняется

(MainForm <> nil) and (MainForm.FormStyle = fsMDIForm)


И за это время выполнится удаление MainForm


 
Игорь Шевченко ©   (2006-11-01 17:49) [55]

@!!ex ©   (01.11.06 17:46) [54]

Особенно интересен момент удаления MainForm у Application. Я к чему говорю - на свете есть много моментов получения AV, просто у ряда из них частота возникновения невелика...


 
@!!ex ©   (2006-11-01 17:51) [56]

Это придирка к примеру, не я его придумал. :)
ДА. Согласен. В таких слуаях AV ОЧЕНЬ редко, но всеже имеет место быть.
И это не есть гуд.
Такие AV хуже всего ловятся.
А когда прога падает раз в месяц и никто не может понять почему.... Программисты получают втыки.


 
YuRock ©   (2006-11-01 17:59) [57]


> А когда прога падает раз в месяц и никто не может понять
> почему....


Мои проги не падают - я же говорил :)
Без перезапуска работают месяцами, пока винда не "попросит" перезагрузки из-за того, что юзер в какую-нибудь игру поиграл или еще что...


 
Игорь Шевченко ©   (2006-11-01 18:01) [58]

@!!ex ©   (01.11.06 17:51) [56]

К сожалению, падающие раз в месяц проги обычно падают по иным причинам, нежели ProcessMessages, вызванный из другого потока.
Кроме того, программы обычно тестируют, как ни странно, выявляя массу ошибок и прочего непредсказуемого поведения.

Я бы не стал рекомендовать использование Application.ProcessMessages из другого потока только по одной причине - это неочевидный код. А любой неочевидный код должен найти свое законное место в корзине.

Других причин (вроде запрета вызова метода VCL-объекта из другого потока, ловля блох в последовательных проверках существования объекта и его теоретического уничтожения между проверками) я не вижу.


 
YuRock ©   (2006-11-01 18:06) [59]


> Eraser ©   (01.11.06 17:20) [52]
> за такое "с умом" с работы попереть могут. я бы призадумался о компетенции такого работника.


Ок, я задумаюсь над своей компетенцией :)


> учти, что даже если тебе полностью понятно,
>  как работает этот код в текущей версии VCL,


Ну, переходить на версию деолфей больше 6 я не собираюсь, и все мысли подчиненных на эту тему обрезаю накорню. Приводя примеры глюков компилятора D7 и выше, на которые я натыкался. Да, обойти их можно, но перелопачивать 70 мегабайт кода никто не будет.


> человек, который
> возможно в будущем будет заниматься поддержкой/развитием
> данного кода может быть не в курсе тонкостей.


А вот за такое с работы попереть могут :)


 
YuRock ©   (2006-11-01 18:14) [60]

> @!!ex
> Eraser

Да, и почему вы решили, что я - за использование Application.ProcessMessages в других потоках? Это удобно, лишь если есть желание компилить проект на Кайликсе. Да и то - сомнительно.

Просто прозвучало утверждение: "Не вздумай!!!..."
А когда я знаю, что это точно можно, а мне говорят, что точно нельзя, я задал вполне логичный вопрос: "Почему?"

И, естественно, ответ типа "Пока поверь мне на слово, а потом подростешь - поумнеешь" меня не полностью удовлетворил :)


 
Eraser ©   (2006-11-01 18:19) [61]

> [59] YuRock ©   (01.11.06 18:06)


> Приводя примеры глюков компилятора D7 и выше, на которые
> я натыкался.

imho 7 - самая стабильная после 3 версия, хотя пользуюсь 10 )

> Ну, переходить на версию деолфей больше 6 я не собираюсь

если кода много переписывать прийдется, тоже не вижу смысла, лучше сразу на C# %-)

> > человек, который
> > возможно в будущем будет заниматься поддержкой/развитием
>
> > данного кода может быть не в курсе тонкостей.
>
>
> А вот за такое с работы попереть могут :)

могут! если он не найдет ошибку, а если найдет, то сразу же перепишет как надо, при этом матеря аффтора того кода )

> Других причин (вроде запрета вызова метода VCL-объекта из
> другого потока, ловля блох в последовательных проверках
> существования объекта и его теоретического уничтожения между
> проверками) я не вижу.

а я не вижу гарантии, что в следующей версии VCL, туда не запуздырят какую-нибудь инструкцию, из-за которой данный код будет "падать". Ведь было же такое и не раз, не мне вам рассказывать.


 
Leonid Troyanovsky ©   (2006-11-01 19:21) [62]


> YuRock ©   (01.11.06 18:14) [60]

> потом подростешь - поумнеешь" меня не полностью удовлетворил


Да, это так оно и есть. Подрастают, но не умнеют.
Отсюда и произрастает неудовлетворенность.

--
Regards, LVT.


 
@!!ex ©   (2006-11-01 20:36) [63]

Помоему уже раз 10 на примерх показали, почему не стоит обращаться к незащищенным переменным и методам из разных потоков.


 
Leonid Troyanovsky ©   (2006-11-01 21:00) [64]


> @!!ex ©   (01.11.06 20:36) [63]

> Помоему уже раз 10 на примерх показали,


Маловато будет.

--
Regards, LVT.


 
YuRock ©   (2006-11-02 15:11) [65]


> @!!ex ©   (01.11.06 20:36) [63]
> Помоему уже раз 10 на примерх показали, почему не стоит
> обращаться к незащищенным переменным и методам из разных
> потоков.


Пока что был только 1 пример - мой, со 100% работающим кодом с ProcessMessages из другого потока.

Остальное - только рассуждения и предположения, не более того.

Если ошибаюсь, или я слепой - напиши номер поста с этими примерами. Желательно - 10-ти примеров. Касающихся сути вопроса, естественно. А почему так делать иногда нельзя - думаю, что знаю это не хуже тебя.

Подчеркиваю - иногда!
Ты ведь пользуешься переменной IsMultiThread в резных потоках, и не засовываешь обращения в CS? Или DecimalSeparator? И таких примеров - действительно миллион. Так зачем чушь нести? И какое это все вообще имеет отношение к теме вопроса?


 
Сергей М. ©   (2006-11-02 15:29) [66]


> YuRock ©   (02.11.06 15:11) [65]


Если ты, дружок ситный, завел всю эту безапелляционную трындельню, то ты, дружок ситный, должен при этом понимать, что объект Application, чей метод ProcessMessages вызывается в потоке X, должен быть создан не иначе как в контексте потока Х.

В противном случает цена твоей трындельне - три копейки в базарный день)


 
YuRock ©   (2006-11-02 15:37) [67]


> Сергей М. ©   (02.11.06 15:29) [66]
> > YuRock ©   (02.11.06 15:11) [65]Если ты, дружок ситный,
>  завел всю эту безапелляционную трындельню, то ты, дружок
> ситный, должен при этом понимать, что объект Application,
>  чей метод ProcessMessages вызывается в потоке X, должен
> быть создан не иначе как в контексте потока Х.В противном
> случает цена твоей трындельне - три копейки в базарный день)


А, что, по твоему есть разница, в каком потоке выделять память? :)))))))))))))


 
Сергей М. ©   (2006-11-02 15:41) [68]


> YuRock ©   (02.11.06 15:37) [67]


Причем здесь выделение, дружок ?

Речь идет об обращении к одному и тому же (уже существующему !) объекту TApplication в контексте более чем одного потока процесса


 
YuRock ©   (2006-11-02 15:48) [69]


> Сергей М. ©   (02.11.06 15:41) [68]
> Речь идет об обращении к одному и тому же (уже
> существующему !) объекту TApplication в контексте более
> чем одного потока процесса


Т.е. если объект создан в потоке X, то в потоке Y его использовать нельзя. Так?


 
Eraser ©   (2006-11-02 16:13) [70]

> [69] YuRock ©   (02.11.06 15:48)

его нельзя использовать в обоих потоках одновременно.


 
Сергей М. ©   (2006-11-02 16:13) [71]


> если объект создан в потоке X, то в потоке Y его использовать
> нельзя. Так?


Репу почесав - можно.
И оную же почесав - нельзя.
Репа программеру дана не только для пожирания чего-то там)


 
YuRock ©   (2006-11-02 16:30) [72]


> Eraser ©   (02.11.06 16:13) [70]
> его нельзя использовать в обоих потоках одновременно.



> Сергей М. ©   (02.11.06 16:13) [71]
> Репу почесав - можно.И оную же почесав - нельзя.


Ребята, зачем вы чушь несете? Вас же вообще ничего незнающие люди читают и верят!!!

Вы пользуетесь компонентами типа Indy, IBX... Да просто классом TThread? Если да - то вы ОБЯЗАТЕЛЬНО ОДНОВРЕМЕННО используете один объект в разных потоках!


 
BiN ©   (2006-11-02 16:36) [73]

Application.ProcessMessages в дополнительном потоке - всё равно что трусы на голове - носить можно, но глупо и чревато менингитом с летальным исходом.


 
Сергей М. ©   (2006-11-02 16:49) [74]


> YuRock ©   (02.11.06 16:30) [72]


> Ребята, зачем вы чушь несете?


Затем чтобы никому не было повадно использовать сабж в своих многопоточных разработках при использовании VCL.

Get/Peek/WaitMessage упразднены уже, а ?


 
Eraser ©   (2006-11-02 16:49) [75]

> [72] YuRock ©   (02.11.06 16:30)


> Если да - то вы ОБЯЗАТЕЛЬНО ОДНОВРЕМЕННО используете один
> объект в разных потоках!

не используем.


 
YuRock ©   (2006-11-02 16:59) [76]


> не используем.


Мда? А никогда не приходилось в TThread.Execute делать такой цикл:


while not Terminated do begin
 //...
end;


а при закрытии приложения, чтобы корректно завершить работу этого потока вызвать, например, Thead1.Terminate или Thead1.Free, который тоже вызовет Terminate?

Если приходилось (а такого не могло не случиться :) ), то да, используете... Переменную класса TThread.FTerminated присваиваете в одном потоке, а используете - в другом... Безо всяких CS. И это - общепринятый метод - когда можно - использовать такое. Одновременно :)


 
BiN ©   (2006-11-02 17:04) [77]


> YuRock ©   (02.11.06 16:59) [76]
>
> Переменную класса TThread.FTerminated
> присваиваете в одном потоке, а используете - в другом...
>  Безо всяких CS. И это - общепринятый метод - когда можно
> - использовать такое. Одновременно :)
>

Все дело в SizeOf(FTerminated).

скучно...


 
Сергей М. ©   (2006-11-02 17:05) [78]


> YuRock ©   (02.11.06 16:59) [76]


Байка о бузине и дядьке.

Диагноз - "В сад" (С)


 
YuRock ©   (2006-11-02 17:09) [79]


> Все дело в SizeOf(FTerminated).


Не только. TThread.FSynchronizeException еще очень большое значение имеет в этом контексте...


 
BiN ©   (2006-11-02 17:15) [80]


> YuRock ©   (02.11.06 17:09) [79]
>
>
> Не только. TThread.FSynchronizeException еще очень большое
> значение имеет в этом контексте...

И какое же значение?


 
Сергей М. ©   (2006-11-02 17:19) [81]


> YuRock ©   (02.11.06 17:09) [79]


Не надо тут уже лепить про атомарность операций ввода/вывода рпо отношению к операндам размером в 1 байт.

Сто раз обсуждалось.

Облажаешься - не отмоешься.


 
YuRock ©   (2006-11-02 17:34) [82]


> И какое же значение?


Не меньшее, чем SizeOf(Boolean)


> Не надо тут уже лепить про атомарность операций ввода/вывода
> рпо отношению к операндам размером в 1 байт.


Вот метод TThread.Destroy, который вызывается в другом потоке:
destructor TThread.Destroy;
begin
 if (FThreadID <> 0) and not FFinished then
 begin
   Terminate;
...
end;


Думаешь, размер FThreadID 1 байт?


> Облажаешься - не отмоешься.


Это не всегда и не по всем заметно... почему-то...


 
Eraser ©   (2006-11-02 19:28) [83]

> [76] YuRock ©   (02.11.06 16:59)

где одновременное использование?

> [82] YuRock ©   (02.11.06 17:34)


> Думаешь, размер FThreadID 1 байт?

метод Destroy выполняется в основном потоке, FThreadID устанавливается тоже в основном потоке. Свойство ThreadID только для чтения, так что никаких конфликтов быть не должно.
Да и, мягко говоря, не удачный ты класс для примера выбрал.. TThread специально спроектирован для работы с доп. потоками, поэтому тут узких мест быть не должно.


 
Eraser ©   (2006-11-02 19:39) [84]

> метод Destroy выполняется в основном потоке

поправочка OnTerminate, т.е. откуда возможен доступ к полям объекта.


 
YuRock ©   (2006-11-02 19:44) [85]


> Eraser ©   (02.11.06 19:28) [83]


Ну так я его именно потому и выбрал :)
А свойство ThreadID, значит, нельзя использовать в коде потока?

Ладно с этим методом. Просто прозвучало утверждение: "Обращения ко всем переменные, использующиеся в разных потоках, обязательно надо синхронизировать, иначе буду AV, зависания и т.д.".

Ну хорошо. Синхронизируем. Перед использованием, скажем, некой переменной пишем:


 EnterCriticalSection( CS );
 //...


И получаем использование переменной CS (как минимум чтение) в разных потоках.

Так вот, меня интересует простой вопрос - зачем вводить в заблуждение читателей форума?


 
YuRock ©   (2006-11-02 19:45) [86]


> Eraser ©   (02.11.06 19:39) [84]
> > метод Destroy выполняется в основном потокепоправочка
> OnTerminate, т.е. откуда возможен доступ к полям объекта.
>


Метод Destroy может выполняться в любом потоке.


 
Eraser ©   (2006-11-02 19:50) [87]

> [85] YuRock ©   (02.11.06 19:44)

пока что в заблуждение всех вводишь ты.

> Обращения ко всем переменные, использующиеся в разных потоках,
> обязательно надо синхронизировать, иначе буду AV, зависания
> и т.д.

ты с этим не соглсен?

из всех правил есть исключения, но это не значит, что нужно игнорировать правила.


 
Eraser ©   (2006-11-02 19:51) [88]

> [86] YuRock ©   (02.11.06 19:45)

согласен, в [84] я себя поправил.


 
YuRock ©   (2006-11-02 19:58) [89]


> ты с этим не соглсен?из всех правил есть исключения, но
> это не значит, что нужно игнорировать правила.


Это не правила. Это логика программ. При чем тут исключения из правил.


> согласен, в [84] я себя поправил.


Я другое имел ввиду. Ты написал, что Destroy вызывается из основного потока, а на самом деле его можно вызывать из какого-угодно.


 
Eraser ©   (2006-11-02 20:07) [90]

> [89] YuRock ©   (02.11.06 19:58)


> Ты написал, что Destroy вызывается из основного потока

вот это я и поправил, имелось ввиду OnTerminate.

> Это логика программ

логика программ в том, что TThread спроектирован для работы в разных потоках, а TApplication - нет.



Страницы: 1 2 3 вся ветка

Форум: "WinAPI";
Текущий архив: 2007.03.11;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.74 MB
Время: 0.076 c
2-1171648748
Malik
2007-02-16 20:59
2007.03.11
Работа с кодом типа String


2-1171703132
lobach
2007-02-17 12:05
2007.03.11
Компоненты для работы с ftp


3-1165992976
VadimSpb
2006-12-13 09:56
2007.03.11
Запись - "фантом"


2-1171959306
vitv
2007-02-20 11:15
2007.03.11
DBGrid11CellClick(Column: TColumn);-вопрос реализации


15-1171652440
Чародей
2007-02-16 22:00
2007.03.11
icq





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский