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

Вниз

Запуск расчета сразу после отрисовки формы   Найти похожие ветки 

 
Franzy   (2009-09-01 13:43) [0]

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

Если пуск прописать в OnCreate, окошко не рисуется вообще до окончания расчета. В OnShow - окошко не активируется. Вставка form1.activate не помогает. Т.е. программа статует как бы в свернутом состоянии. Причем при этом "висит" и не разворачивается, несмотря на вставки Application.processmessages при каждом обновлении отчета.

Как это реализовать правильно?


 
clickmaker ©   (2009-09-01 13:48) [1]

> Как это реализовать правильно?

Запускать расчет в отдельном потоке. Тогда не суть важно, в каком событии.
Оповещать различные компоненты отчета о прогрессе расчета можно через PostMessage форме.


 
Franzy   (2009-09-01 13:50) [2]

Забыл уточнить: сами расчетные процедуры находятся в подключаемой dll.


 
Медвежонок Пятачок ©   (2009-09-01 13:50) [3]

и правильно что забыл. ибо уточнение лишнее.


 
Franzy   (2009-09-01 14:03) [4]

А еще варианты есть?


 
clickmaker ©   (2009-09-01 14:09) [5]

> А еще варианты есть?

Application.ProcessMessages в цикле расчета после очередной итерации.
А чем поток не устраивает?


 
sniknik ©   (2009-09-01 14:11) [6]

можно послать самому сете сообщение и уже в нем чтото делать, точно будет после OnShow, если посылать в нем.
или банально поставить таймер, включать там же и выключать после 1й сработки.
или поток стартовать, к тому времени когда нужда будет синхронизироваться для отрисовки результатов, форма уже успеет появиться.


 
Медвежонок Пятачок ©   (2009-09-01 14:14) [7]

у него же уже колбаки вовсю прогресс расчета рисуют. чем не место для процессмессаджес?


 
Franzy   (2009-09-01 14:16) [8]

А внутри потока можно обращаться к объектам формы?


 
Медвежонок Пятачок ©   (2009-09-01 14:17) [9]

можно, если поток главный.


 
Franzy   (2009-09-01 14:22) [10]

Я так понимаю, проблема в том, что onCreate и onShow вызываются прямо ПЕРЕД тем, как окончатся соотв. процессы. А мне нужно ПОСЛЕ их окончания :( Похоже, придется использовать треды. Кстати, сразу вопрос по ним: можно ли обращаться внутри треда к элементам формы (если я объвлю класс треда внутри модуля формы)?


 
Медвежонок Пятачок ©   (2009-09-01 14:26) [11]

если я объвлю класс треда внутри модуля формы)?

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


 
Сергей М. ©   (2009-09-01 14:29) [12]


> Franzy   (01.09.09 14:22) [10]



> мне нужно ПОСЛЕ их окончания


Просто создавай форму ПОСЛЕ их окончания.


 
Медвежонок Пятачок ©   (2009-09-01 14:29) [13]

Автор, в обработчике OnCreate посылай сам себе сообщение c помощью postmessage

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


 
Сергей М. ©   (2009-09-01 14:31) [14]


> можно ли обращаться внутри треда к элементам формы


Это смотря что ты подразумеваешь под "элементами формы"


 
Franzy   (2009-09-01 14:41) [15]

Я хочу разобраться с тредами, мне это может пригодиться в других приложениях :)

Сделал через треды так:


unit Main;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, Math;

type
 TForm1 = class(TForm)
 .....
 end;

 TMyThread = class(TThread)
 private
   { Private declarations }
 protected
   procedure Execute; override;
 end;

var
 Form1: TForm1;
 GridThread : TMyThread;

///////////////////////////////  

implementation

{$R *.dfm}

.......

procedure TMyThread.Execute;
begin

....

end;

procedure TForm1.FormCreate(Sender: TObject);
begin

 GridThread:=TMyThread.Create(false);
 GridThread.Execute;

end;

end.


Вылетает с ошибкой "Canvas does not allow drawing"


 
Медвежонок Пятачок ©   (2009-09-01 14:45) [16]

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


 
Franzy   (2009-09-01 14:46) [17]

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


 
Franzy   (2009-09-01 14:46) [18]


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


Там не один десяток страниц :(


 
Anatoly Podgoretsky ©   (2009-09-01 14:47) [19]

> Franzy  (01.09.2009 14:41:15)  [15]

GridThread.Execute; запускай в отдельном методе, после начальных обработчиков.


 
Медвежонок Пятачок ©   (2009-09-01 14:48) [20]

Там не один десяток страниц :(

Может тебе и ответы давать многоточием?
:)))


 
Franzy   (2009-09-01 14:49) [21]

Закомментиовал коллбэк (в смысле, функция теперь ничего не делает), но ошибка все равно выскакивает.


 
Медвежонок Пятачок ©   (2009-09-01 14:50) [22]

Сделал тестовое приложение, в котором только тред, меняющий капшн формы - все работает нормально, ошибки нет.

мало тредов потому и нет. а еще просто потому нет потому что повезло.

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


 
Медвежонок Пятачок ©   (2009-09-01 14:52) [23]

но ошибка все равно выскакивает.

в [9] можно узнать почему это происходит.


 
Franzy   (2009-09-01 14:54) [24]


> GridThread.Execute; запускай в отдельном методе, после начальных
> обработчиков.


Вот такой код прекрасно работает:


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs;

type
 TForm1 = class(TForm)
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

 TMyThread = class(TThread)
 private
   { Private declarations }
 protected
   procedure Execute; override;
 end;

var
 Form1: TForm1;
 MyThread: TMyThread;

implementation

{$R *.dfm}

procedure TMyThread.Execute;
begin
 form1.caption:="Hello World";
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 MyThread:=TMyThread.create(false);
 MyThread.Execute;
end;

end.


 
clickmaker ©   (2009-09-01 14:55) [25]

> GridThread.Execute;

это не нужно.
если параметр в конструкторе false, он сразу запустится.
если true, то после установки свойств треда нужно вызвать Resume


 
Медвежонок Пятачок ©   (2009-09-01 14:56) [26]

ну так и используй его. а тот код,  что с ошибкой сотри.


 
clickmaker ©   (2009-09-01 14:57) [27]

> Вот такой код прекрасно работает

потому что ты просто запустил метод Execute явно и в основном потоке. Смысла отдельного потока здесь теряется. С таким же успехом это мог быть TSomeObject.Execute


 
Franzy   (2009-09-01 14:57) [28]

Объясните, тогда как правильно, я не понимаю и хочу разобраться. В справке все очень кратко, только про Synchronize что-то упоминается.


 
Franzy   (2009-09-01 15:05) [29]

Ага, ошибка появляется, если внутри execute использовать ShowMessage! Почему так?


 
Медвежонок Пятачок ©   (2009-09-01 15:27) [30]

у попа была собака, он ее любил ....


 
Franzy   (2009-09-01 15:36) [31]

2Медвежонок Пятачок
Если не можете ничего сказать по существу, не флеймите, пожалуйста, для этого, кажется, есть отдельный подфорум. У меня есть реальная проблема и я хочу с ней разобраться.


 
clickmaker ©   (2009-09-01 15:36) [32]

> Почему так?

потому что
When you use objects from the class hierarchy, their properties and methods are not guaranteed to be thread-safe. That is, accessing properties or executing methods may perform some actions that use memory which is not protected from the actions of other threads.

Если уж сильно приспичило показать сообщение в потоке, используй апишную MessageBox()


 
Amoeba ©   (2009-09-01 15:37) [33]


> только про Synchronize что-то упоминается.

Вот-вот! И не просто так упоминается! И не только в справке, а также и в тексте, который автоматически генерируется при создании модуля потока.


 
Franzy   (2009-09-01 15:41) [34]

2sniknik

Вариант с postmessage самому себе сработал, спасибо.

Хотя с тредами по-прежнему не понятно :(


 
Leonid Troyanovsky ©   (2009-09-01 15:44) [35]


> Franzy   (01.09.09 15:36) [31]

>  У меня есть реальная проблема и я хочу с ней разобраться.

Проблема не одна.
В dll от Synchronize практической пользы нет.

--
Regards, LVT.


 
sniknik ©   (2009-09-01 15:45) [36]

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


 
Юрий Зотов ©   (2009-09-01 15:50) [37]

> Franzy   (01.09.09 15:05) [29]

1. Расчет запускаете в отдельном потоке из OnShow главной формы. При создании объекта TMyThread форма передает ему свой хэндл и тот запоминает полученный хэндл в своем поле с именем MainFormHandle.

2 Определяете структуру данных, которые поток будет передавать форме, например:
type
 TMyData = record
   data1: integer;
   data2: string[255];
   ...
 end;
 PMyData = ^TMyData;


3. В секции interface модуля потока определяете сообщение для передачи данных:
const
 WM_UserPlus100 = WM_USER + 100;


4. Метод Execute потока:
procedure TMyThread.Execute;
var
 MyData : TMyData;
begin
 while not Terminated do
 begin
   MyData.data1 := ...;
   MyData.data2 := ...;
   ...
   PostMessage(MainFormHandle, WM_UserPlus100, @MyData, 0);
   ... // Здесь выполняем шаг расчета
 end
end;


5. В секции protected формы делаете метод:
procedure WMUserPlus100(var Message: TMessage); message WM_UserPlus100;
и реализуете этот метод:
procedure TForm1.WMUserPlus100(var Message: TMessage);
begin
 inherited;
 with PMyData(Message.WParam)^ do
 begin
   ProgressBar1.Position := data1;
   Edit1.Test := data2;
   ...
 end
end;


 
Franzy   (2009-09-01 15:56) [38]

2clickmaker
А, т.е. они имели ввиду class hierarchy в широком смысле, т.е. вообще все объекты и контролы? Я просто так понял, что речь идет об объектах, которые одновременно используются в разных потоках. Ясно. Т.е. нужно избегать прямого обращения к свойствам и методам объектов, а вместо это использовать WinAPI и мессаджи?


 
Franzy   (2009-09-01 15:59) [39]


> Расчет запускаете в отдельном потоке из OnShow главной формы


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


 
Amoeba ©   (2009-09-01 16:01) [40]

http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1370


 
Юрий Зотов ©   (2009-09-01 16:11) [41]

> Franzy   (01.09.09 15:59) [39]

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

Не будет. Событие OnShow возникает, когда свойство Visible формы меняется и становится равным True. Вы же не собираетесь "моргать" главной формой, насколько я понимаю?
:o)


 
clickmaker ©   (2009-09-01 16:15) [42]

> Т.е. нужно избегать прямого обращения к свойствам и методам
> объектов, а вместо это использовать WinAPI и мессаджи?

в не главных потоках, и смотря, к каким методам и свойствам. К тем, которые затрагивают vcl-ную часть UI - да.


 
Leonid Troyanovsky ©   (2009-09-01 16:15) [43]


> sniknik ©   (01.09.09 15:45) [36]

>  каптион присваивается посылкой сообщения (WM_SETTEXT),

А там не SendMessage, but Perform, так что и с заголовком не все чисто.

--
Regards, LVT.


 
Franzy   (2009-09-01 16:18) [44]

Так, с потоками разобрался, кажется, спасибо. Я правильно понял, что "главный поток" - это само приложение, в котором все эти треды объявляются?

Но сделал все через отправку сообщения самому себе :) Там мороки существенно меньше.


 
oldman ©   (2009-09-01 16:27) [45]


> Franzy   (01.09.09 13:43)  


Будь проще.
Запусти нужный тебе расчет в отдельном потоке из TTimer.
При запуске потока дизабли таймер.
Форма отрисуется, будет активной, поток пойдет.
Время старта таймера поставь опытным путем.


 
Leonid Troyanovsky ©   (2009-09-01 17:48) [46]


> Franzy   (01.09.09 16:18) [44]

> Так, с потоками разобрался, кажется, спасибо. Я правильно
> понял, что "главный поток" - это само приложение

MainThreadId - идентификатор первичного потока, т.е., того, что
создает CreateProcess и возвращает в PROCESS_INFORMATION structure.
Для обычных дельфийский приложений он же и VCL thread.

--
Regards, LVT.



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

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

Наверх





Память: 0.57 MB
Время: 0.047 c
15-1250899237
Tirael
2009-08-22 04:00
2009.10.25
как называется игрушка


2-1251352990
Евгений Р.
2009-08-27 10:03
2009.10.25
Как изменить высоту строк tDbGrid?


15-1250800206
Юрий
2009-08-21 00:30
2009.10.25
С днем рождения ! 21 августа 2009 пятница


2-1251642682
tonich
2009-08-30 18:31
2009.10.25
Блокировка потоков


1-1221818257
Jolik
2008-09-19 13:57
2009.10.25
Как передать форму по сети :)





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