Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2015.11.01;
Скачать: [xml.tar.bz2];

Вниз

Таймер и поток   Найти похожие ветки 

 
Кто б сомневался ©   (2015-03-09 02:35) [0]

Непонятно..
Есть базовый vcl поток и второй поток. Со второго потока создается и запускается таймер. При срабатывании WM_TIMER код будет выполняться в каком потоке и почему?

constructor TSimpleTimer.Create(AInterval: integer);
begin
 inherited Create;
 fWindowHWND := Classes.AllocateHWnd(WndProc);
 fInterval := AInterval;
end;

procedure TSimpleTimer.WndProc(var AMsg: TMessage);
begin
 with AMsg do
 begin
   if (Msg = WM_TIMER) then
   begin
     Assert(Assigned(fOnTimer), "Set OnTimer event");
     if Assigned(fOnTimer) then
       fOnTimer(Self)
   end
   else
     Result := DefWindowProc(fWindowHWND, Msg, wParam, lParam);
 end;
end;


Classes.pas:
function AllocateHWnd(const AMethod: TWndMethod): HWND;
var
 TempClass: TWndClass;
 ClassRegistered: Boolean;
begin
 UtilWindowClass.hInstance := HInstance;
 ClassRegistered := GetClassInfo(HInstance, UtilWindowClass.lpszClassName,
   TempClass);
 if not ClassRegistered or (TempClass.lpfnWndProc <> @DefWindowProc) then
 begin
   if ClassRegistered then
     Winapi.Windows.UnregisterClass(UtilWindowClass.lpszClassName, HInstance);
   Winapi.Windows.RegisterClass(UtilWindowClass);
 end;
 Result := CreateWindowEx(WS_EX_TOOLWINDOW, UtilWindowClass.lpszClassName,
   "", WS_POPUP {+ 0}, 0, 0, 0, 0, 0, 0, HInstance, nil);
 if Assigned(AMethod) then
   SetWindowLongPtr(Result, GWL_WNDPROC, IntPtr(MakeObjectInstance(AMethod)));
end;


Спасибо.


 
Кто б сомневался ©   (2015-03-09 02:36) [1]

Вот блин. Не ту кнопку нажал.

constructor TSimpleTimer.Create(AInterval: integer);
begin
 inherited Create;
 fWindowHWND := Classes.AllocateHWnd(WndProc);
 fInterval := AInterval;
end;

procedure TSimpleTimer.WndProc(var AMsg: TMessage);
begin
 with AMsg do
 begin
   if (Msg = WM_TIMER) then
   begin
     Assert(Assigned(fOnTimer), "Set OnTimer event");
     if Assigned(fOnTimer) then
       fOnTimer(Self)
   end
   else
     Result := DefWindowProc(fWindowHWND, Msg, wParam, lParam);
 end;
end;


Classes.pas:
function AllocateHWnd(const AMethod: TWndMethod): HWND;
var
 TempClass: TWndClass;
 ClassRegistered: Boolean;
begin
 UtilWindowClass.hInstance := HInstance;
 ClassRegistered := GetClassInfo(HInstance, UtilWindowClass.lpszClassName,
   TempClass);
 if not ClassRegistered or (TempClass.lpfnWndProc <> @DefWindowProc) then
 begin
   if ClassRegistered then
     Winapi.Windows.UnregisterClass(UtilWindowClass.lpszClassName, HInstance);
   Winapi.Windows.RegisterClass(UtilWindowClass);
 end;
 Result := CreateWindowEx(WS_EX_TOOLWINDOW, UtilWindowClass.lpszClassName,
   "", WS_POPUP {+ 0}, 0, 0, 0, 0, 0, 0, HInstance, nil);
 if Assigned(AMethod) then
   SetWindowLongPtr(Result, GWL_WNDPROC, IntPtr(MakeObjectInstance(AMethod)));
end;


 
Кто б сомневался ©   (2015-03-09 02:40) [2]

В базовом, т.к. там цикл GetMessage?


 
DVM ©   (2015-03-09 10:01) [3]


> Кто б сомневался ©   (09.03.15 02:35) 


> При срабатывании WM_TIMER код будет выполняться в каком
> потоке и почему?

Почему бы не вызвать во всех нужных точках программы GetCurrentThreadId и не сравнить числа?


> В базовом, т.к. там цикл GetMessage?

У тебя окно принадлежит второму потоку, а цикл находится в первом. Этот цикл выбирает сообщения из очереди первого потока, сообщения посланные окнам второго потока туда не попадают.


 
Leonid Troyanovsky ©   (2015-03-09 10:22) [4]


> Кто б сомневался ©   (09.03.15 02:40) [2]

> В базовом, т.к. там цикл GetMessage?

Ни в одном.
Бо, установивший таймер поток должен иметь цикл обработки сообщений.
RTFM:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx

Про окно вторичном потоке см. также
http://rsdn.ru/forum/delphi/883505

--
Regards, LVT.


 
Кто б сомневался ©   (2015-03-09 22:49) [5]


> > В базовом, т.к. там цикл GetMessage?
>
> У тебя окно принадлежит второму потоку, а цикл находится
> в первом. Этот цикл выбирает сообщения из очереди первого
> потока, сообщения посланные окнам второго потока туда не
> попадают.


Решил по другому делать. Буду в цикле выполнять код, до этого засекаться время, после выполнения кода делать sleep потока на время константу минус время потраченное на код.
Чтобы прозрачно отработал второй поток и в будущем избежать дальнейшей путанницы.


 
DVM ©   (2015-03-10 10:14) [6]


> Буду в цикле выполнять код, до этого засекаться время, после
> выполнения кода делать sleep потока на время константу минус
> время потраченное на код.

Костыльно как то выглядит. Вообще, имхо, любой код, где используется sleep() уже подозрителен.


 
Кто б сомневался ©   (2015-03-10 14:07) [7]


> Вообще, имхо, любой код, где используется sleep() уже подозрителен.


Да ладно, подозрительный.
Как раз для паузы (в моем случае это таймаут) - идеально. И поток отдает свое время другим, и пауза считается и легко отследить отладчиком..


 
Кто б сомневался ©   (2015-03-10 14:16) [8]

Костыльно это когда через WM_TIMER, во втором потоке, специально созданному для WM_TIMER невидимому окну.
И хрен знает что с ним случиться, если второй поток случайно навернется.


> и пауза считается


В данном случае это событие (Event) - отсчет таймаута, которое срабатывает каждую секунду, потом в вышестоящих классах отправляется WM на форму.


 
vuk ©   (2015-03-10 14:21) [9]

Если нужен таймер в потоке, то лучше Waitable Timer использовать.


 
Кто б сомневался ©   (2015-03-10 14:38) [10]


> vuk ©   (10.03.15 14:21) [9]
>
> Если нужен таймер в потоке, то лучше Waitable Timer использовать.
>


Это больше для пула потоков подходит. А если все в одном потоке происходит, то имхо проще sleep.


 
MBo ©   (2015-03-10 15:09) [11]

Лучше о задаче расскажи, а то на проблему XYZ смахивает.


 
vuk ©   (2015-03-10 15:13) [12]

Зачем для пула? Создал таймер, выставил период и вперед - WaitForSingleObject/WaitForMultipleObjects. Дождался, отработал, ждешь следующего сигнала. И никаких костылей в виде окон и оконных функций.


 
DVM ©   (2015-03-10 15:14) [13]


> Кто б сомневался ©   (10.03.15 14:38) [10]


> А если все в одном потоке происходит, то имхо проще sleep.


> Да ладно, подозрительный.

Особенно вся эта костыльность проявляет себя при завершении такого потока или при завершении программы. Sleep нельзя прервать, все сидят и ждут когда же этот Sleep вернет управление. Особенно если интервал в Sleep большой. Еще смешнее когда интервал в силу других ошибок в программе становится значительный - все виснет. Есть же события, Waitable Timers, WaitFor функции наконец. Нужды использовать Sleep нет абсолютно никакой, разве что для отладки.


 
Кто б сомневался ©   (2015-03-10 15:45) [14]


> Есть же события, Waitable Timers, WaitFor функции наконец.
>  


ну и чем он функционально отличается от sleep (если используется в одном потоке, а не в пуле)? Так же поток будет пропускать CPU время (waitfor = sleep),  пока таймер отсигналит.


> Нужды использовать Sleep нет абсолютно никакой, разве что
> для отладки.


Ты путаешь sleep и suspendThread - это разные вещи, которые по разному работают.

Sleep - This function causes a thread to relinquish the remainder of its time slice and become unrunnable for an interval based on the value of dwMilliseconds.

suspendThread - suspending a thread causes the thread to stop executing user-mode (application) code. Как пишет Рихтер там около тысячи тактов, довольно тяжелая вещь.


 
Кто б сомневался ©   (2015-03-10 15:51) [15]

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


 
jack128 ©   (2015-03-10 16:03) [16]


> Со второго потока создается и запускается таймер.

MakeObjectInstance не потокобезопасная функция, поэтому VCL"ный таймер нельзя создавать в доп потоке.


 
DVM ©   (2015-03-10 16:20) [17]


> Кто б сомневался ©   (10.03.15 15:45) [14]


> ну и чем он функционально отличается от sleep (если используется
> в одном потоке, а не в пуле)? Так же поток будет пропускать
> CPU время (waitfor = sleep),  пока таймер отсигналит.

1) Sleep нельзя прервать. Для преодоления этого недостатка был создан еще один костыль - SleepEx.
2) Интервал времени, который реально даст Sleep зависит от положения звезд на небе и с очень большой натяжкой сравним с тем что написано в скобках.
3) Крутить Sleep с небольшим интервалом в цикле - это значит обрекать поток на постоянную работу. Он будет засыпать-просыпаться вместо того, чтобы просто ждать нужного события. В целом это пагубно отражается на быстродействии всей системы.


> Ты путаешь sleep и suspendThread - это разные вещи, которые
> по разному работают.

я ничего не путаю, о suspendThread вообще речи не идет.


 
DVM ©   (2015-03-10 16:26) [18]


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

Если кто-то может подумать, что это фигня и ловля блох, то следует помнить о мобильных платформах.


 
Кто б сомневался ©   (2015-03-10 16:43) [19]


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


В случае Waitable таймера и слип - я вижу разницу только в точности. И то я сомневаюсь что там большая разница, если использовать timeBeginPeriod для sleep.
(To increase the accuracy of the sleep interval, call the timeGetDevCaps function to determine the supported minimum timer resolution and the timeBeginPeriod function to set the timer resolution to its minimum. )

А вот с точки зрения работы двух методов - это шило на мыло, только больше писанины. Имхо.

при Waitable таймере -
тот же цикл,
создаем, запускаем таймер, далее
- WaitFor (технически это тот же sleep - поток также будет пропускать CPU время).
- Через секунду таймер сработал, сделали работу,
- опять WaitFor (sleep).

И чем это отличается от цикла и sleep?
Тем что в sleep всего одна строчка.


 
Кто б сомневался ©   (2015-03-10 16:59) [20]


> DVM ©   (10.03.15 16:26) [18]

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


 
Кто б сомневался ©   (2015-03-10 17:05) [21]


> Просто в моем случае нужно каждую секунду отсчитать и возбудить
> событие.


В моем случае в одном потоке проверяется закрылся ли один из нескольких процессов или файлов. Процессов и файлов может быть много. Поток один.


 
DVM ©   (2015-03-10 17:09) [22]


> Кто б сомневался ©   (10.03.15 16:43) [19]

Отличия в том, что ты функцию ожидания WaitForMultipleObjects ты всегда можешь прервать немедленно и быстро, если ждать в функции два объекта: событие завершения потока и таймер. У тебя в параметрах Sleep  число 1000 стоит? Не очень много. А если бы там минута стояла?


 
Кто б сомневался ©   (2015-03-10 17:50) [23]


> DVM ©   (10.03.15 17:09) [22]
У тебя в параметрах Sleep  число 1000 стоит?


1000 - минус время потраченное на проверку.

Плюс таким образом еще и считаем сколько прошло секунд. Плюс каждую секунду отправляем WM на форму.
Не, имхо все таки вариант со sleep больше здесь подходит. Хотя надо вечером еще подумать.


 
DVM ©   (2015-03-10 18:07) [24]


> 1000 - минус время потраченное на проверку.

главное отрицательное число не получить:

var
 a: DWORD;
begin
 a := 1001;
 Sleep(1000 - a);  // <= висим
end;


 
Кто б сомневался ©   (2015-03-10 18:12) [25]


> DVM ©   (10.03.15 18:07) [24]


Да это я в курсе.
А ты бы сделал через WaitForMultipleObjects?
Но он чаще чем за секунду будет срабатывать. Соотвественно поток чаще будет входить в ожидание WaitFor. Возможно за секунду много раз.
А waitFor этот тот же sleep по факту.


 
Rouse_ ©   (2015-03-10 18:22) [26]


> Кто б сомневался ©   (10.03.15 16:59) [20]
> Я понял, мы про разное говорим. Просто в моем случае нужно
> каждую секунду отсчитать и возбудить событие.

Так может быть тебе дополнительная нить вообще не нужна в таком случае?


 
Кто б сомневался ©   (2015-03-10 18:30) [27]


> Rouse_ ©   (10.03.15 18:22) [26]
>
>
> > Кто б сомневался ©   (10.03.15 16:59) [20]
> > Я понял, мы про разное говорим. Просто в моем случае нужно
>
> > каждую секунду отсчитать и возбудить событие.
>
> Так может быть тебе дополнительная нить вообще не нужна
> в таком случае?


Не, нить точно нужна. Это параллельная задача.
GUI только ловит сообщения от потоков.


 
Rouse_ ©   (2015-03-10 19:01) [28]

Ага, те. нагрузка все-же в нити, а наружу только нотификации.
Есть два варианта: первый через внешний эвент, который будет ждать нить на WaitFor а само событие перезапускается в основной нити (грубо аналог машины состояний реализующий задачу перекрестка с множеством светофоров на одном таймере)
Второй вариант: использование таймера с калбэком, а необходимые для калбэка данные хранить в TLS

Я реализовывал оба варианта, оба хорошие, но первый немного посложнее при наличии множества нитей.


 
Rouse_ ©   (2015-03-10 19:04) [29]

Собственно с самим TLS ручками даже не придется работать, т.к. это все уже реализовано посредством глобальной "treadvar"


 
Rouse_ ©   (2015-03-10 19:08) [30]

Грубо по второму варианту:

1. в Execute нити запоминаем Self во внешней переменной
threadvar: MyThreadObject;

2. Вызываем SetTimer с указанием не HWID окна а адреса калбэка

3. в калбэке вытаскиваем экземпляр класса из MyThreadObject (он будет уникален для каждой нити) и работаем как есть.


 
Кто б сомневался ©   (2015-03-10 19:09) [31]


> А ты бы сделал через WaitForMultipleObjects?

Итак процессы и файлы уже закрываются, ждем их закрытия, показывая юзеру обратный отсчет (таймаут) на каждый объект.

Прикинул в уме - все таки через sleep код прозрачней для программиста получается и меньше (не нужно массив заводить для WaitForMultipleObjects, проверять его каждый раз, а потом еще и обратно ассоциировать с текущими классами, плюс у WaitFor все равно нужно ставить таймаут в секунду - вдруг объект не закроется, плюс корректировать время, чтобы раз в сек. отправлять сообщение).

Вот кстати DVM"у пример, когда вариант со Sleep более удобный, чем с WaitFor.


 
Rouse_ ©   (2015-03-10 19:11) [32]

ЗЗЫ: но есть нюанс, если придется резко тормозить твое ПО, то лучше все-же делать через внешние события, в противном случае допнити будут продолжать висеть


 
Rouse_ ©   (2015-03-10 19:14) [33]


> Вот кстати DVM"у пример, когда вариант со Sleep более удобный,
>  чем с WaitFor.

Sleep - это просто обертка над WaitFor (ну это так, для самообразования, если что :)


 
Дмитрий С ©   (2015-03-10 19:14) [34]


> использование таймера с калбэком

А разве калбек будет работать без цикла GetMessage в том же потоке?


 
Кто б сомневался ©   (2015-03-10 19:16) [35]


> Rouse_ ©   (10.03.15 19:08) [30]


Даже не знаю. Я просто в сообщении передаю ссылку на потоко-защищенный класс. Да и все.


 
Rouse_ ©   (2015-03-10 19:16) [36]


> Дмитрий С ©   (10.03.15 19:14) [34]
> А разве калбек будет работать без цикла GetMessage в том
> же потоке?

Дим, ты начинаешь меня пугать :)


 
Rouse_ ©   (2015-03-10 19:18) [37]


> Кто б сомневался ©   (10.03.15 19:16) [35]
> Даже не знаю. Я просто в сообщении передаю ссылку на потоко-
> защищенный класс. Да и все.

Ну вот попробуй, получится я знаю.


 
Дмитрий С ©   (2015-03-10 19:29) [38]


> Дим, ты начинаешь меня пугать :)

Либо я что-то в теме пропустил, либо пугаешь меня ты.

Я вообще так думаю: Если калбек должен вызываться по таймеру, то кто-то его должен вызывать явно (не по прерыванию же). Ну а кто, кроме оконного цикла? (GetMessage, PeekMessage, TranslateMessage или DispatchMessage - я не помню кого именно и как надо вызывать). Что не так то?


 
Rouse_ ©   (2015-03-10 19:41) [39]


> Что не так то?

Практически все :)
Для калбэка ЦВС не нужен, он вообще тут избыточен ибо играет второстепенную роль.
Я тебе секрет открою - вся асинхронность на ЦВС строится через калбэки, даже сокеты с их асинхронной моделью :)
Читай внимательней MSDN - оно наше все :)


 
Rouse_ ©   (2015-03-10 19:45) [40]

Даже наверное перефразирую - вся эта чехарда с ЦВС (который привязан к конкретной нити, где создано окно) - это всего лишь результат калбэков.
Все эти окна - сообщения, ЦВС - это все наведенное. На самом деле все работает совсем по другому :)


 
Кто б сомневался ©   (2015-03-10 20:00) [41]

Я чет ЦВС расшифровать не могу :)


 
Кто б сомневался ©   (2015-03-10 20:01) [42]

ЦОС - могу, а ЦВС ...?


 
Rouse_ ©   (2015-03-10 20:06) [43]

Семен-Семеныч :)
Цикл Выборки Сообщений


 
Дмитрий С ©   (2015-03-10 22:10) [44]

Сань, можно пример работы setTimer без цвс? Поток займи, например, sleep-ом? Я с ходу написал - калбек не вызывается.


 
Кто б сомневался ©   (2015-03-10 22:17) [45]


> Дмитрий С ©   (10.03.15 22:10) [44]


Дык в SetTimer можно колбэк фукнцию указать

lpTimerFunc [in, optional]

Type: TIMERPROC

A pointer to the function to be notified when the time-out value elapses. For more information about the function, see TimerProc. If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application queue. The hwnd member of the message"s MSG structure contains the value of the hWnd parameter.

https://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx


 
Дмитрий С ©   (2015-03-10 22:52) [46]

Так а кто это калбэк вызовет? Он как раз и вызывается одной из функцией цвс. Нет?
А иначе получится либо ещё один поток, либо прерывание.


 
Кто б сомневался ©   (2015-03-10 23:02) [47]


> Он как раз и вызывается одной из функцией цвс. Нет?


Ну да.
WM_TIMER и колбэк вызывается в GetMessage и PeekMessage.

When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.


 
Rouse_ ©   (2015-03-10 23:04) [48]

Давай угадаю, ты вызвал в execute, после чего нить завершилась?


 
Rouse_ ©   (2015-03-10 23:20) [49]

Дам намек, в сервисах окон и цвс нет, таймеры есть ;)


 
Eraser ©   (2015-03-11 04:35) [50]


> Кто б сомневался ©   (09.03.15 02:35) 

посмотри как сделаны TJvTimer и TJvThreadTimer из JEDI VCL, но или вообще их и используй.


 
Кто б сомневался ©   (2015-03-11 15:04) [51]


> Eraser ©   (11.03.15 04:35) [50]


Спасибо. Надо глянуть.
DVM тоже спасибо.
И вообще всем спасибо за помощь. Всем лучи добра! :)

Решил все таки через sleep. Т.к. там еще будет учитываться время работы кода + таймер.
Оптимальный вариант как с точки зрения производительности так и для чтения кода программистом - последнее время я на это часто обращаю внимание - т.к. много времени уходит на разбор чужого запутанного кода.
Причем народ умудряется совершенно банальные вещи запутывать. Типа передавать что-то через события в местах, где лучше использовать сообщения или ссылку на метод через стэк. В итоге из за вложенности ненаследованных классов одно и то же событие передается через 6-7 классов цепочкой через класс ядра и в каждом классе дублируется OnEventBlablabla и путаешься откуда что идет.


 
Кто б сомневался ©   (2015-03-11 15:45) [52]


> Eraser ©   (11.03.15 04:35) [50]
>
>
> > Кто б сомневался ©   (09.03.15 02:35)
>
> посмотри как сделаны TJvTimer и TJvThreadTimer из JEDI VCL,
>  но или вообще их и используй.


Ниче интересного.
Там тоже sleep используют. Наследуют от TThread + sleep (причем без timeBeginPeriod) + Synchronize. А TJvTimer это обычный TTimer почти точь в точь.


 
DVM ©   (2015-03-11 22:56) [53]

Вот, кстати, вспомнил давнишнюю статью про таймеры:

http://www.delphikingdom.com/asp/viewitem.asp?catalogID=434


 
Дмитрий Белькевич ©   (2015-03-12 22:16) [54]

>посмотри как сделаны TJvTimer и TJvThreadTimer из JEDI VCL, но или вообще их и используй.

могу кинуть свою реализацию таймера. работает с помощью FEvent.WaitFor(FInterval);

из фич - работает в параллельном потоке сам и может вызывать параллельный поток, никак на vcl не завязан, в отличие от стандартного, с которым в потоках невозможно нормально работать.


 
Дмитрий Белькевич ©   (2015-03-12 22:17) [55]

перепробовал с пяток сторонних, в конце концов плюнул - сам написал (впрочем, как часто и бывает :) )


 
Кто б сомневался ©   (2015-03-15 16:55) [56]


> из фич - работает в параллельном потоке сам и может вызывать
> параллельный поток,


Мне не нравиться идея что таймер создает отдельный поток. Это слишком затратно.
+ Имхо вообще лучше код не привязывать к конкретному классу потока, это только путает, а делать напр. так:

TWorkThread.RunInThread(DoSmthThread, DoOnTerminate);


 
Кто б сомневался ©   (2015-03-15 16:57) [57]

class procedure TWorkThread.RunInThread(aProc: TProc; const aOnTerminate: TNotifyEvent = nil);
begin
 with TWorkThread.Create(true) do
 begin
   FreeOnTerminate := true;
   fProc := aProc;
   OnTerminate := aOnTerminate;
   Start;
 end;
end;


 
Leonid Troyanovsky ©   (2015-03-17 10:47) [58]


> Кто б сомневался ©   (15.03.15 16:57) [57]

> class procedure TWorkThread.RunInThread(aProc:

Напр. так делать не надо, бо есть конструкторы (вирт.)

--
Regards, LVT.


 
Кто б сомневался ©   (2015-03-17 15:19) [59]


> Leonid Troyanovsky ©   (17.03.15 10:47) [58]
>
>
> > Кто б сомневался ©   (15.03.15 16:57) [57]
>
> > class procedure TWorkThread.RunInThread(aProc:
>
> Напр. так делать не надо, бо есть конструкторы (вирт.)


Не понял, какие конструкторы?
И как они пересекаются со статичной процедурой в этом случае?

Это все делается для того, чтобы человеку (а не компилятору) было проще.
Вообще я даже формы так вызываю - TMyForm.ShowModal - и на выходе результат.  Всего одна строчка, а вся реализация в модуле формы.  
Очень удобно, а главное не запутывает.

Предлагаю вам создать топик, "почему так нельзя делать", чтобы все присоединились.


 
Кто б сомневался ©   (2015-03-17 15:22) [60]


> TMyForm.ShowModal -

Поправочка:

* TMyForm.ShowMyForm


 
Kerk ©   (2015-03-17 16:24) [61]


> Кто б сомневался ©   (15.03.15 16:55) [56]
>
>
> > из фич - работает в параллельном потоке сам и может вызывать
> > параллельный поток,
>
>
> Мне не нравиться идея что таймер создает отдельный поток.
>  Это слишком затратно.
> + Имхо вообще лучше код не привязывать к конкретному классу
> потока, это только путает, а делать напр. так:
>
> TWorkThread.RunInThread(DoSmthThread, DoOnTerminate);

Есть же TThread.CreateAnonymousThread() или даже TTask.Run()


 
Leonid Troyanovsky ©   (2015-03-17 17:31) [62]


> Кто б сомневался ©   (17.03.15 15:19) [59]

> Это все делается для того, чтобы человеку (а не компилятору)
> было проще.Вообще я даже формы так вызываю - TMyForm.ShowModal
> - и на выходе результат.  Всего одна строчка, а вся реализация
> в модуле формы.  Очень удобно, а главное не запутывает.

Надо повесить на стену (на ^J) шаблон:

with TMyForm.Create(nil) do
 try
   ..
   ShowModal;
 finally
   Free;
 end;

Очень удобно и не запутывает.

--
Regards, LVT.


 
Кто б сомневался ©   (2015-03-17 18:12) [63]


> Очень удобно и не запутывает.


Запутывать он будет когда смешается с другим кодом. Плюс пройдет пару лет.
Это ж очевидно: много текста = больше времени на его чтение. Меньше текста = меньше времени.

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

Много по малу = много.

Да и логичней это как то - когда код для работы формы написан в модуле этой формы.


 
Leonid Troyanovsky ©   (2015-03-17 18:42) [64]


> Кто б сомневался ©   (17.03.15 18:12) [63]

>  и вы частенько будете на него попадать при чтении и разработке
> проекта, так почему бы его не спрятать?

Если спрятать, то и будет непонятно.
Без сборщиков мусора вся работа с объектами так и выглядит:
создали-поработали-уничтожили.

> Да и логичней это как то - когда код для работы формы
> написан в модуле этой формы.

Для работы формы - в ее модуле, а _с_ формой - в другом,
скажем, в модуле главной. Можно даже "на ходу" наследника
сочинить (и создать-показать-разрушить).

--
Regards, LVT.



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

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

Наверх





Память: 0.64 MB
Время: 0.003 c
15-1426601509
Кто б сомневался
2015-03-17 17:11
2015.11.01
Каким НЕ должно быть ПО


15-1425857735
Кто б сомневался
2015-03-09 02:35
2015.11.01
Таймер и поток


15-1426411817
Pavia
2015-03-15 12:30
2015.11.01
Кластер на халяву


15-1426714204
Юрий
2015-03-19 00:30
2015.11.01
С днем рождения ! 19 марта 2015 четверг


15-1426768249
Pavelnk
2015-03-19 15:30
2015.11.01
С php на delphi





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский