![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Обращение к VCL объектам из потока
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
Anatoly Podgoretsky (2009-02-11 15:13:00) [21]> markers (11.02.2009 14:38:36) [36]
Аааааааааааааа!
KSergey (2009-02-11 14:47:00) [22]> markers © (11.02.09 14:38) [36]
> Ещё какие-то притензия, предложения, cоветы?
Лучше всю задачу обсказать. ТОгда можно посоветовать как это все организовать.
Однако надо четко понимать, что наличие доп. потока (да хоть тыщи) не дает в общем случае возможности немедленно заставлять реагировать приложение на кнопку "стоп". Нажимать дает, реагировать - нет.
Сергей М. (2009-02-11 14:45:00) [23]
> markers
> проблемы при медленном соединении (нельзя обломать), потому
> и занялся потоками
Потоки не ускорят соединение.
markers (2009-02-11 14:38:00) [24]Согласен так правильней, я так делаю когда обяъявляю более 1-й переменной, а когда 1 то так.... Хорошо! Спасибо! Учту! Ещё какие-то притензия, предложения, cоветы?
Сергей М. (2009-02-11 14:36:00) [25]
> подскажите свои рекомендации
Думаю, что я не ошибусь, если KSergey © не обратил внимания на твой грубейший ляп именно потому, что такое форматирование
procedure TMainForm.ChekUpdatesMBTClick(Sender: TObject);
var updForm : TUpdForm;
begin
на фоне большушего фрагмента кода попросту "замыливает глаз"
А вот так
procedure TMainForm.ChekUpdatesMBTClick(Sender: TObject);
var
updForm : TUpdForm;// по одному ид-ру в каждой новой строке и обязательно с общепринятым фиксированным отступом
begin
локальность проблемного идентификатора сразу бы бросилась в глаза.
markers (2009-02-11 14:19:00) [26]Созрела мысль создать поток который будет последовательно стартить другие потоки, но насколько я понял это не гуд, хотя с другой стороны основной поток проги поступает так же как и созданный мною поток.
To: Сергей М.
Ну подскажите свои рекомендации в особенности по логике и по форматированию? Я жду ваших советов!
TO Anatoly Podgoretsky
Дыг, знаю естественно и много где юзаю, однако это не даёт мне возможности во время задумчивости обломать это всё легально по батону "Стоп".
Вообще у меня сам код обновления написан, но так как он выполняется в основном потоке, есть проблемы при медленном соединении (нельзя обломать), потому и занялся потоками.
Спасибо!
Anatoly Podgoretsky (2009-02-11 14:12:00) [27]> markers (11.02.2009 14:01:30) [30]
Что бы не был заморожен, чаще всего решается с помощью Application/ProcessMessages.
Сергей М. (2009-02-11 14:09:00) [28]
> Почему код как вы его назвали "говнокод"?
Хотя бы потому что его форматирование, мягко говоря, оставляет желать лучшего.
Про логику я промолчу - она не выдерживает никакой критики.
markers (2009-02-11 14:04:00) [29]Была мысль выполнять всю работу в основном потоке, а потокам вызвать и показывать какую-нибудь формочку с текстом "Жуём", нехотелось т.к. множество форм - зло и были ещё причины.
markers (2009-02-11 14:01:00) [30]Я конечно изменяюсь, но думаю что не стоит так сильмо промывать мои косточки.... Почему код как вы его назвали "говнокод"? Просто непридумал как сделать лучше без таймера последовательное выполнение задач в потоке... т.к. мне надо чтоб основной поток небыл загружен для реализации отмены и т.д.. т.к. процессы некоторые продолжительны, либо пользователь захотел отказаться от скачивания обновлений в процессе их скачивания... просто как мне показалось что вызвав и ожидая выполнения потока в обработчике начатия кнопки Старт не избавит основной поток от "задумчевости".... Можно было бы запустить все потоки и идти пить чай, но нужна последовательность... потому сделал таймер чтоб он поглядывал выполнился ли поток, если да то стартовал другой, если выполнился последний поток, отключал таймер сам себя и всё.
Сергей М. (2009-02-11 13:50:00) [31]
> Плохиш © (11.02.09 13:37) [26]
Буржуи проклятые !
Нет бы написать по рабоче-крестьянски)
Anatoly Podgoretsky (2009-02-11 13:48:00) [32]> KSergey (11.02.2009 13:17:19) [19]
Зачем искать вторую траблу, если первая не устранена.
markers (2009-02-11 13:45:00) [33]Плохиш
KSergey
Точняк!!! Большое спасибо вам и всем остальным :))
Плохиш (2009-02-11 13:37:00) [34]
> Сергей М. © (11.02.09 13:33) [25]
Оно и понятно, это ж на чуждом языке написано.
Сергей М. (2009-02-11 13:33:00) [35]
> Плохиш © (11.02.09 13:31) [23]
Он получил Inaccessible value и засим успокоился)
Сергей М. (2009-02-11 13:32:00) [36]
> точно! проглядел
При лицезрении говнокода это обычное дело)
Плохиш (2009-02-11 13:31:00) [37]
> 3) Делаю степ-бай-степ, дельфя выкидывает еррорименно при
> выполнении изменений объекта формы, дальше идёт обработка
> её try except`ом...
Как баран перед новыми воротами, так и ты с отладчиком. Посмотреть значения переменных при выполнении проблеммной строки мозгов не хватает?
markers (2009-02-11 13:25:00) [38]1) На счёт Execute, повторяю в самом начале дебага, и счас стоит Resume проблема от этого не решилась....
2) Ладно если дебажить не один и тот же на всём протяжении код.... а то что не делаешь всё спотыкается именно об это....
3) Делаю степ-бай-степ, дельфя выкидывает еррор именно при выполнении изменений объекта формы, дальше идёт обработка её try except`ом...
4) Насчёт того что виновник в другом месте, появилась одна мысль, счас проверю.
KSergey (2009-02-11 13:23:00) [39]> Плохиш © (11.02.09 13:21) [20]
Ёлы-палы, точно! проглядел :(
Плохиш (2009-02-11 13:21:00) [40]
> markers © (11.02.09 12:59) [14]
>
> To Palladin
> UpdForm: TUpdForm создаётся в родительской форме.....
Да создаётся, только указатель на неё присваивается локальной переменной, о которой модуль, где описана эта форма ничего не знает.