Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.09.08;
Скачать: CL | DM;

Вниз

Проблемы с 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;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.025 c
14-24690
Мазут Береговой
2003-08-19 09:58
2003.09.08
Ну, вот и дождались!


3-24359
VID
2003-08-17 15:06
2003.09.08
FIBDataSet, Blob-поле


1-24495
servs
2003-08-22 18:59
2003.09.08
Глобальный отлов exception


6-24584
Chaos
2003-07-04 16:46
2003.09.08
Как узнать ср-вами D6 что кто-то подключился к моему компу


6-24610
UserName
2003-07-03 20:47
2003.09.08
record и SendBuf ReceiveBuf