Форум: "Основная";
Текущий архив: 2003.09.08;
Скачать: [xml.tar.bz2];
ВнизПроблемы с TThread 2... Найти похожие ветки
← →
¤ZDima¤ (2003-08-21 23:02) [0]Знающие люди, помогите разобраться с нитями(TThread) – привожу код, в чём ошибка ниже...
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,{!!!->}jpeg{<-!!!};
type
TMyThread = class(TThread)
private protected
procedure DoWork;
procedure DoAnWork;
procedure Execute; override;
end;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private public end;
var
Form1: TForm1;
t:TMyThread;
ki:integer=0;
files:TStringList;
implementation
{$R *.dfm}
procedure TMyThread.Execute;
begin
DoWork;
t.FreeOnTerminate:=true;
t.Free;
end;
procedure TMyThread.DoAnWork;
begin
Form1.Caption:=IntToStr(round((ki/files.Count)*100))+"% Done";
Form1.Label1.Caption:="File:"+files[ki-1];
end;
procedure TMyThread.DoWork;
var i:integer; b:TBitmap;
j:TJPEGImage; img:TPicture;
begin
files:=TStringList.Create;
files.LoadFromFile("c:\fileList.txt");
//В фаёле "c:\fileList.txt" находиться список
//файлов(с путями) формата bmp и jpg
CreateDir("c:\zdima\");
b:=TBitmap.Create;
j:=TJPEGImage.Create;
img:=TPicture.Create;
for i:=0 to files.Count-1 do begin
img.LoadFromFile(files[i]);
b.Width:=img.Width;
b.Height:=img.Height;
b.Canvas.Draw(0,0,img.Graphic);
j.Assign(b);
j.Compress;
j.SaveToFile("c:\zdima\"+inttostr(i)+".jpg");
ki:=i+1;
Synchronize(DoAnWork);
end;
b.Free;
j.Free;
img.Free;
files.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
t:=TMyThread.Create(false);
end;
end.
Всё вроде-бы понятно, но если двинуть мышь то возникнет ошибка "Out of system resources"или “Не верный дескриптор”... Причём даже если убрать Synchronize(DoAnWork); ошибка остаётся. Подскажите, что нужно сделать, стоб работало???...
P.S. ответ лучше в виде кода...
← →
3APA3A (2003-08-21 23:21) [1]А если мышь не двигать? Все нормально?
← →
Palladin (2003-08-21 23:29) [2]доктор сказал в морг - значит в морг
причины смерти
1 идентификаторы некоторых объектов - глобальные
2 что за чушь в Execute?
DoWork;
t.FreeOnTerminate:=true;
t.Free;
3 мусор в голове, надо бы упорядочить, математикой занятся...
← →
jack128 (2003-08-21 23:44) [3]ну строка
> t.FreeOnTerminate:=true;
вполне в стиле
procedure TForm1.Button1Click(Sender: TObject);
begin
Form1.Enabled := True;
...
Form1.Enabled := False;
end;
А вот эта строка t.Free; это сильно!
> ¤ZDima¤ © (21.08.03 23:02)
Да и еще, я смотрю, ты уверен что пишешь без ошибок - ни одного обработчика оных не вищу...
← →
Borealis (2003-08-21 23:45) [4]
> ¤ZDima¤ © (21.08.03 23:02)
> Знающие люди, помогите разобраться с нитями
Ну ты тут и наворотил. Безбутылки не разберёшь... :)
Особенно здесь:
> procedure TMyThread.Execute;
> begin
> DoWork;
> t.FreeOnTerminate:=true;
> t.Free;
> end;
Во-первых, почему "t."? Во-вторых, зачем "t.Free;"?
У меня кстати и так всё работает и никаких ошибок не даёт, но этот кусок кода перепиши:
procedure TMyThread.Execute;
begin
FreeOnTerminate := True;
DoWork;
end;
← →
имя (2003-08-22 01:42) [5]Удалено модератором
← →
Ihor Osov'yak (2003-08-22 01:46) [6]А если по делу - почитай книжки, как опрятный код писать..
А то в таком бардаке что-то смотреть нет желания совсем..
И подумай над Palladin © (21.08.03 23:29), особенно в части глобальных идентификаторов.. Может и не в них дело - но при виде такого кода иного желания, чем отослать к учебникам, не возникает..
Сорри за резкость, но надеюсь, что выводы правильные сделаешь..
← →
¤ZDima¤ (2003-08-22 10:55) [7]С этим - прикол вышел
> t.FreeOnTerminate:=true;
> t.Free;
- я попутал, сорри... Сам долго ржал:))))
Да, и чего вам в коде не нравиться - всё понятно(мне:))))...
И ещё обидно, что по делу совет дали только два чела...
------
Ну так как сделать без глобальных идентефикаторов?
Иль кто ссылку на статью даст какую...
← →
MVova (2003-08-22 11:06) [8]procedure TMyThread.DoWork;
var i:integer; b:TBitmap;
j:TJPEGImage; img:TPicture;
begin
files:=TStringList.Create;
Нельзя из потоков (если их несколько одновременно) обращатся к глобальным переменным без синхронизации.
Можно files:TStringList перенести в клас потока, если логически возможно(я в суть задачи не смотрел), или работать с ним как с глобальным синхронизуя доступ и убрав создание files из потока.
← →
¤ZDima¤ (2003-08-22 20:32) [9]Короче, я сильно упростил код, даже комментарии добавил!!! Вот он:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,{!!!->}jpeg{<-!!!};
type
TMyThread = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private public end;
var
t:TMyThread;
Form1: TForm1;
implementation
{$R *.dfm}
procedure TMyThread.Execute;
begin
t.FreeOnTerminate:=true;
DoWork;
end;
procedure TMyThread.DoWork;
var i:integer; b:TBitmap;
j:TJPEGImage; img:TPicture;
files:TStringList;
begin
files:=TStringList.Create;
files.LoadFromFile("c:\fileList.txt");
//В файле "c:\fileList.txt" находиться список
//файлов (с путями) формата bmp и jpg
CreateDir("c:\zdima\");
b:=TBitmap.Create;
j:=TJPEGImage.Create;
img:=TPicture.Create;
for i:=0 to files.Count-1 do begin
img.LoadFromFile(files[i]);//грузим файл в TPicture
//т.к. туда грузятся и jpg и bmp
b.Width:=img.Width; //Перерисовываем
b.Height:=img.Height; //загруженный рисунок
b.Canvas.Draw(0,0,img.Graphic);//на Bitmap
j.Assign(b);//тут и так понятно (кому нет - идите)
j.Compress;
j.SaveToFile("c:\zdima\"+inttostr(i)+".jpg");
end;
b.Free; //Всем
j.Free; //спасибо
img.Free; //Все
files.Free; //свободны
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
t:=TMyThread.Create(false);
end;
end.
Глобальных переменны нет (я даже пробовал t:TMyThread; убирать), и... не работает!!!:(
Кто виноват я знаю… А вот ЧТО ДЕЛАТЬ???
P.S. Пишите письма мелким шрифтом.
← →
OptiX (2003-08-22 23:36) [10]Вы когда вызываете DoWork не забывайте синхронизировать вызов;
...
Synchronize(DoWork);
...
← →
¤ZDima¤ (2003-08-23 09:11) [11]OptiX
Synchronize(DoWork); - пропадает смысл потока - если он будит делать свою работу синхронно - основной паток в это время не будит работать...
MVova
Подскажите, как обращаться к переменным через синхронизацию...
Synchronize только процедуры вызывает...
← →
y-soft (2003-08-23 09:53) [12]>¤ZDima¤ © (23.08.03 09:11) [11]
Подскажите, как обращаться к переменным через синхронизацию...
В Вашем случае - через критические секции, причем не только в доп. потоке, но и в главном тоже во всех случаях, когда осуществляется изменение значения переменной...
uses
...SyncObjs;
...
var
Padlock : TCriticalSection;
GlobalVar : string;
...
Padlock.Enter;
GlobalVar := NewValue;
Padlock.Leave;
Или даже так:
Padlock.Enter;
try
...
GlobalVar := NewValue;
...
finally
Padlock.Leave;
end;
initialization
Padlock := TCriticalSection.Create;
finalization
Padlock.Free;
end.
А вообще такая синхронизация осуществляется и другими способами: с использованием Мьютексов/Семафоров, функций InterlockedXXX или постановкой в очередь с помощью, например, посылки сообщений окну. Весь смысл - исключить одновременный доступ разных потоков к переменной...
P.S. В использовании глобальных переменных ничего особо страшного нет. Страшно использовать их неправильным образом...
← →
¤ZDima¤ (2003-08-24 10:45) [13]y-soft? спасибо за информацию, но я сделал новый пример вообще без глобальный переменных (см. Выше), а ошиька осталась:((
Так в чём же ошибка?
← →
y-soft (2003-08-24 20:01) [14]С ходу не скажу, но сразу же бросается в глаза отсутствие каких-либо обработчиков возможных ошибок, а такие ошибки потенциально возможны практически в каждой строчке приведенного кода. В таком виде даже отладить нормально невозможно...
Если выскакивает именно "Неверный дескриптор", то это может относится как к файлам, так и к графике, "Out of resources" тоже много к чему...
Выход один - расставить блоки try...finally, try...except и смотреть в отладчике, лучше построчно...
← →
¤ZDima¤ (2003-08-25 10:43) [15]ошиька возникает на строчке
j.Compress; - на этой
j.SaveToFile("c:\zdima\"+inttostr(i)+".jpg");
И вообще она возникает когда даёшь нагрузку - например пошевелишь мышью, если нажать на старт и ничего не делать, то всё работает...
← →
y-soft (2003-08-25 12:06) [16]Очень похоже, что где-то в дополнительном потоке происходит конфликт с главным потоком из-за одновременного обращения к функциям перерисовки - возможно код VCL для TJpegImage.Compress не является потокобезопасным:(
Попробуйте вынести для отладки код, выполняющийся в потоке в главный поток и проверьте, исчезает ли ошибка...
← →
Erik Ivanov (2003-08-25 14:11) [17]Или j.Compress выполнить в Synchronize
← →
¤ZDima¤ (2003-08-26 13:46) [18]В основном потоке всё работает, как часы.
При Synchronize(j.Compress), всё та же ошибка:(
Что делать?
← →
Erik (2003-08-26 13:53) [19]Похоже у тебя TJPEGImage скачай другой компонент и с ним попробуй. Можно еще ему перерисовку запретить.
← →
y-soft (2003-08-26 21:07) [20]Что-то мне подсказывает, что надо обратить внимание на эту строчку:
j.Assign(b);//тут и так понятно (кому нет - идите)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.09.08;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.009 c