Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
11-24401
reformator
2002-12-31 00:10
2003.09.08
как реализовать FloatToStr в KOL е?


8-24564
wara
2003-05-12 11:35
2003.09.08
Какие данные хранятся вместе с графикой в графических файлах?


3-24368
P0tia
2003-08-15 21:45
2003.09.08
DbGrid & dBase


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


3-24333
Илайдж
2003-08-18 14:45
2003.09.08
ADO





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