Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Обращение к VCL объектам из потока


Страницы:   1 2 3

markers ©   (2009-02-11 12:33:00) 

Здраствуйте!
Давно не писал потоки, а тут потребовалось.....
Изучил доку по потокам http://www.interface.ru/home.asp?artId=6105и на данном сайте везде из потока прекрасно обращяются к объектам VCL, а у меня эксепшн....
Имеем главную форму которая пораждает в случае необходимости дополнительную форму с потоками таким способом:
procedure TMainForm.ChekUpdatesMBTClick(Sender: TObject);
var updForm : TUpdForm;
begin
 updForm := TUpdForm.Create(Self);
 with updForm do
  begin
   ShowModal;
   Free;
  end;
end;

Вот код вызывеемой формы:
unit UpdateFrm;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls, XPMenu, SystemUnit, ComCtrls, Buttons;

type
 OperType = (otuCheck, otuProg, otuBD, otuImages);
 TMyThread = class(tthread)
 private
   UpdateType : OperType;
 protected
   procedure execute; override;
 end;
 TUpdForm = class(TForm)
   GroupBox1: TGroupBox;
   StatusBar: TStatusBar;
   CheckBox1: TCheckBox;
   CheckBox2: TCheckBox;
   CheckBox3: TCheckBox;
   Start: TButton;
   GroupBox2: TGroupBox;
   Cancel: TButton;
   ProgressBar: TProgressBar;
   Log: TMemo;
   StopUpdate: TBitBtn;
   OperStart: TTimer;
   procedure FormCreate(Sender: TObject);
   procedure StartClick(Sender: TObject);
   procedure FormShow(Sender: TObject);
   procedure OperStartTimer(Sender: TObject);
   procedure StopUpdateClick(Sender: TObject);
   procedure Updater_pbi;
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 UpdForm: TUpdForm;
 MyThread : TMyThread;
 CountTraf : Int64;
 NextOper : OperType;
 CurOper : OperType;
 Breaked : Boolean;
 ThreadFinish : Boolean = True;

implementation
{$R *.dfm}
uses MainUnit, RegExpr, IniFiles;

procedure TUpdForm.Updater_pbi;
begin
try
 if CurOper = otuCheck Then
  begin
   Log.Lines.Add('Проверка необходимости обновления ядра программы'); // На этот код возникает Access violetion
   sleep(15);
   ThreadFinish := True;
  end
 else if CurOper = otuProg Then
  begin
   sleep(15);
   ThreadFinish := True;
  end
 else if CurOper = otuBD Then
  begin
   sleep(15);
   ThreadFinish := True;
  end
 else if CurOper = otuImages Then
  begin
   sleep(15);
   ThreadFinish := True;
  end;
except
 on E:Exception do Mess(e.Message, mtError)
end;
end;

{ TMyThread }
procedure TMyThread.execute;
begin
CurOper := UpdateType;
Synchronize(UpdForm.Updater_pbi);
end;

{ TUpdateForm }
procedure TUpdForm.FormCreate(Sender: TObject);
begin
if DrivType = SDT_CDROM then
 begin
  Mess('Обновление баз программы при работе с CD, недоступно!'+#13#10+'Произведите установку программы на жёсткий диск!',mtWarning);
  Cancel.Click;
  exit;
 end;
 if Trim(UpdateServer) = '' then UpdateServer := defupdateserver;
end;

procedure TUpdForm.StartClick(Sender: TObject);
begin
 Log.Clear;
 if MainForm.ChekUpdatesMBT.Tag = 1 then MainForm.ChekUpdatesMBT.Tag := 0; // Нужно для запуска обновления автоматом (Ранее в проге было получено согласие пользователя)
 Log.Lines.Add('Начало обновления');
 NextOper := otuCheck;
 Breaked := False;
 OperStart.Enabled := True;
 StopUpdate.Enabled := False;
end;

procedure TUpdForm.FormShow(Sender: TObject);
begin
 if MainForm.ChekUpdatesMBT.Tag = 1 then Start.Click;
end;

procedure TUpdForm.OperStartTimer(Sender: TObject);
begin
 Application.ProcessMessages;
 inherited;
 if ThreadFinish then
  begin
   ThreadFinish := False;
   MyThread := TMyThread.create(True);
   MyThread.FreeOnTerminate := True;
   MyThread.UpdateType := NextOper;
   MyThread.Priority := tpNormal;
   MyThread.execute; // Пробовал в начале Resume, эффект тот-же

   if NextOper = otuImages then OperStart.Enabled := False
   else if NextOper = otuBD then NextOper := otuImages
   else if NextOper = otuProg then NextOper := otuBD
   else if NextOper = otuCheck then NextOper := otuProg;
  end;
end;

procedure TUpdForm.StopUpdateClick(Sender: TObject);
begin
Breaked := True;
end;

end.

Прошу прощения за кривость кода..... Пробовал сувать код исполняемый в потоке пихать и в Execution и в отдельную функу в классе TMyThread всё одно, ошибка... (поставил комент на том месте где еррорит...). Так же пробовал обращатся к другим объектам а не только к объекту Log типа Tmemo


Cobalt   (2009-02-16 00:21:00) [1]

2 markers ©
Если нужно обмениваться данными с потоком, к примеру,  нужно знать состояние работы потока, процент выполнения :

поток пишет куда-то свои данные, а с формы - таймер, обновляет состояние.

Или поток посылает форме сообщение, по которому она понимает, что надо обновить отображение, и считывает эти данные с какого-то глобального потокозащищенного объекта.


markers   (2009-02-13 06:02:00) [2]

> Dennis I. Komarov ©   (12.02.09 15:34) [57]
А вы о этом, да можно. Но впринцепи после того как мне указали на неопределённый индетификатор, я немного переделал и работа с VCL из потока пошла :)
Всем спасибо!


Dennis I. Komarov   (2009-02-12 15:34:00) [3]


> Порождённый поток и будет за всё отвечать, но нужно чтоб
> поток самой программы не блокировался для возможности реализации
> остановки.
> Думал делать всю работу в потоке самой программы (основной),
>  а для визуализации породить окно в потоке которое бы отображало
> процесс не очень удобно для меня.


goto [55]


markers   (2009-02-12 14:16:00) [4]


> Dennis I. Komarov ©   (12.02.09 14:05) [55]
> т.е. база после скачивания тупо меняется на новую... ладно,
>  проехалиДля реализации данной задачи совсем не вижу необходимости
> потоком управлять визуальными объектами...передавайте параметры
> работы потока в основной поток, а он пусть уже сам отвечает
> за визуализацию...

Порождённый поток и будет за всё отвечать, но нужно чтоб поток самой программы не блокировался для возможности реализации остановки.
Думал делать всю работу в потоке самой программы (основной), а для визуализации породить окно в потоке которое бы отображало процесс не очень удобно для меня.
На счёт экономии трафика: я имелл ввиду когда все данные Ядро, бд, картинки обновлялись бы одновременно в нескольких потоках. Т.е я не хочу чтоб на середине обновления проги, бд, картинок, юзер захотел бы это дело обломать потратив в пустую трафик на некодаченое ядро проги и БД. (Картинки качаются в цикле по одной, и в данном случае облом для них абсолютно не критичен).
Вообщем в моём понимании операции должны идти последовательно, чтоб в случае облома пользователь не много терял в трафике, т.к. повторяюсь основное использование программы в городах где трафик стоит дорого и не во всех есть безлимит. А ядро программы весит порядка метра, БД порядка 3 метров, ну а картинки в зависимости от их количества :) в среднем по 7 кб на картинку


Dennis I. Komarov   (2009-02-12 14:05:00) [5]

т.е. база после скачивания тупо меняется на новую... ладно, проехали

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


markers   (2009-02-12 13:47:00) [6]

Dennis I. Komarov ©   (12.02.09 12:07) [53]
> Что будет, если при обновлении БД "обломать" процесс?

Ничего страшного, т.к. замена и реаницилизация БД происходит после успешной скачки. Но не хочется чтоб пользователь тратил лишний трафик, т.к. эта программа используется в достаточно мелких городах где не всегда есть безлимитник и дешёвый трафик..


Dennis I. Komarov   (2009-02-12 12:07:00) [7]


> Сам процесс обновления написан, отлажен и работает, но всё
> делается в одном потоке без возможности обломать процесс.
>

Что будет, если при обновлении БД "обломать" процесс?


markers   (2009-02-12 11:54:00) [8]

> Anatoly Podgoretsky ©   (12.02.09 11:09) [51]
скачивание производится процедуру httpgetfile найденую в инете.
procedure HttpGetFile(url,filename:string);
var
 F:File;
 ResumePos,BufferLen,SumSize:DWORD;
 hSession, hURL: HInternet;
 Buffer: array[1..1024] of Byte;
 err: boolean;
begin
 SumSize:=0;ResumePos:=0;

 AssignFile(F,filename);
 IF FileExists(filename) then
 begin
   Reset(f,1);
   ResumePos:=FileSize(F);
   Seek(F,FileSize(F));
 end else ReWrite(f,1);

 hSession:=InternetOpen('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)',0,nil,nil,0);
 hURL:=InternetOpenURL(hSession,PChar(url),nil,0,0,0);
 InternetQueryDataAvailable(hURL, SumSize,0,0);
 label4.Caption:=IntToStr(SumSize);
 if ResumePos>0 then InternetSetFilePointer(hURL,ResumePos,nil,0,0);

 repeat
  err:=InternetReadFile(hURL, @Buffer,SizeOf(Buffer),BufferLen);
  if err=false then begin ShowMessage('Error');exit;end;
  BlockWrite(f,Buffer,BufferLen);
  Application.Processmessages;
 until (BufferLen=0);
end;

Только я её подправил для того чтоб было ясно сколько скачалось и прочее.
Паралельность не нужна, т.к. оно этапное..... сначало ядро проги если есть свежей, потом БД (если есть новей), а потом картинки (если изменились/добавились)...


Anatoly Podgoretsky   (2009-02-12 11:09:00) [9]

> markers  (12.02.2009 10:42:50)  [50]

Это не про потоки, а про сокеты и их поддержку.


markers   (2009-02-12 10:42:00) [10]

> Anatoly Podgoretsky ©   (12.02.09 09:58) [48]
> автор дошел до формулировки/объяснения задачи, когда должен
> был это сделать в исходном сообщение [0]

Дыг вопрос то был в другом, не как сделать, а в чём проблема потому задача появилась сейчас когда мне стало интересы варианты решения задачи.
> Anatoly Podgoretsky ©   (12.02.09 10:00) [49]
> вижу тебе нужно ассинхронное исполнение, а ты почему то
> используешь блокирующие синхронные методы.

Не подскажите где можно скурить эту тему, в двух доках по потокам на эту тему нет ничего...

Заранее спасибо!


Anatoly Podgoretsky   (2009-02-12 10:00:00) [11]

> markers  (12.02.2009 6:03:47)  [47]

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


Anatoly Podgoretsky   (2009-02-12 09:58:00) [12]

> markers  (12.02.2009 5:43:45)  [45]

Вот только к 45 сообщению автор дошел до формулировки/объяснения задачи, когда должен был это сделать в исходном сообщение [0]


markers   (2009-02-12 06:03:00) [13]

Fix markers ©   (12.02.09 05:43) [45]
> но всё делается в одном потоке без возможности обломать
Поправлю себя во избежании недопонимания.... делается всё в основном потоке программы, т.е. как обычно в процедуре обработки к примеру батона  и без создания потоков.


markers   (2009-02-12 05:57:00) [14]

Кстати, я счас подумал и решил, что проверку необходимости обновления проги, БД, картинок надо сделать рядом с непосредственно обновлением того или иного... Но опять же нужен управляющий поток... чтоб выполнялось обновления последовательно, чтоб затраченный скажем трафик при обновлении БД не улетучился при обнаружении новой версии ядра проги. Да и хотелось бы чтоб прогресс бар был "ровным" в том смысле чтоб каждый поток не дёргал его в зависимости от % выполнения.
Вообщем жду ваших предложений!
Спасибо!


markers   (2009-02-12 05:43:00) [15]

To: Сергей М.

> Потоки не ускорят соединение.

Ктоб спорил, это был пример той операции которую юзер захотел бы обломать...
To: KSergey

> приложение на кнопку "стоп". Нажимать дает, реагировать
> - нет.

Тоже не спорю, просто я уже могу обработать нажатие кнопки и завершить немедленно поток/потоки. А при работе всего в одном потоке я не только не могу остоновить работу по внешнему событию (возбуждённому не в обработке задачи), но и банально не смогу нажать батон...

To: All
Каждый делает ляпы и иногда грубые, но это не означает что нужно человека старатся уличить в мелочах яркий пример про медленное соединение, явно можно было понять что я пропустил слово "Например" ?

Вообще у меня такая задача.....:
Имеем форму на которых есть 3 CheckBox`а (Обновление ядра, БД, картинок), пользователь отмечает то что он хочет выполнять и нажимает кнопку Старт. Происходит (В потоке) проверка необходимости обновления выбранных пунктов. Затем собственно обновление тех пунктов что выбрал пользователь и обновления нашлись. Проверка необходимости обновления картинок достаточна длительна (прмиерно минуту), т.к. скачивается инишник с именем=хешем файла, программа обходит каталог картинок и составляет подобный список в финише сравниваются эти списки и скачиваются изменившиеся/новые картинки. Сам процесс обновления написан, отлажен и работает, но всё делается в одном потоке без возможности обломать процесс.


Palladin   (2009-02-11 19:32:00) [16]

Вообще то про

> UpdForm: TUpdForm; - объекта не существует,

это я еще раньше чем усе сказал :) но тот, кому это предназначалось, намека не понял...


Сергей М.   (2009-02-11 17:01:00) [17]


> это поклеп


Тогда приношу свои извинения)


Anatoly Podgoretsky   (2009-02-11 16:58:00) [18]


> Это совет или претензия? :)

Это диагноз.

> это Анатолию, наверно. что-то прищемили, и он не смог сдержать
> эмоций)

А это поклеп.

Парень ленивый и даже не стесняется это громко заявить.


Сергей М.   (2009-02-11 16:38:00) [19]


> KSergey ©   (11.02.09 16:29) [40]


Это ни ни другое - это Анатолию, наверно. что-то прищемили, и он не смог сдержать эмоций)


KSergey   (2009-02-11 16:29:00) [20]

> Anatoly Podgoretsky ©   (11.02.09 15:13) [39]

Это совет или претензия? :)


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо