Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.03.11;
Скачать: CL | DM;

Вниз

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 вся ветка

Текущий архив: 2007.03.11;
Скачать: CL | DM;

Наверх




Память: 0.76 MB
Время: 0.039 c
4-1161758488
leonidus
2006-10-25 10:41
2007.03.11
Не удается получить заголовок окна


1-1169040865
Strate
2007-01-17 16:34
2007.03.11
Потоки


8-1147019307
Константинов
2006-05-07 20:28
2007.03.11
WaveOut


6-1158902135
Николас
2006-09-22 09:15
2007.03.11
Серьезный TCP сервер.


2-1172077776
KLAUS
2007-02-21 20:09
2007.03.11
Секции в файле