Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.02.10;
Скачать: [xml.tar.bz2];

Вниз

Уважаемые Дельфисты - проблемма с потоками   Найти похожие ветки 

 
denisWW   (2004-01-28 00:23) [0]

Уважаемые Дельфисты - проблемма с потоками
всё начинается просто:
Type
TMapThread=class(TThread)
private
protected
Procedure Execute; override;
procedure DoTerminate; override;
public
end;

var
MapThread:TMapThread;
Const
MapThreadActive:Boolean=False;

implementation

Procedure TMapThread.DoTerminate;
Begin
MapThread.FreeOnTerminate:=True;
MapThreadActive:=False;
End;

Procedure TMapThread.Execute;
Begin With Form1 Do Begin
MapThreadActive:=True;
..........
здесь идёт кусок кода который может выполнятся достаточно долго .....
{поиск и работа с рисунками в цикле
существует в этом цикле и метод такой:

if Terminated Then Exit;

для быстрого выхода из цикла}
..........

End End;

Вызов процедуры возможен очень быстро и
я хочу тогда тормозить поток действующий и запускать его заново
текст такой

If MapThreadActive and (MapThread<>Nil) Then With MapThread Do Begin
Terminate;
WaitFor;
End;
MapThread:=TMapThread.Create(False);

и так по кругу

Проблемма такая через несколько быстрых циклов XP-начинает работать неправильно - но без явной ошибки
а вот Win98 даёт ошибку явно:
System error: Code 6
Неверный дескриптор


где зараза зарыта!!!????????

я тестировал
ощущения что перед Terminate;WaitFor; оператор With MapThread Do теряет указатель на поток :(


 
denisWW   (2004-01-28 00:37) [1]

Вот такой Execute; уже вызывает ошибку

Procedure TMapThread.Execute;
Var
IniExp:TIniFile;
Begin With Form1 Do Try
MapThreadActive:=True;
IniExp:=TIniFile.Create(ShellTreeView.SelectedFolder.PathName+"\Default.ini");

Finally
IniExp.Free;
End End;

как видите я использую обьект ShellTreeView


 
DenisWW   (2004-01-28 00:53) [2]

Сделал так и всёравно ошибка!!!!!
Procedure TMapThread.WWW;
Var IniExp:TIniFile;
Begin
IniExp:=TIniFile.Create(Form1.ShellTreeView.SelectedFolder.PathName+"\Default.ini");
IniExp.Free;
End;

Procedure TMapThread.Execute;
Begin With Form1 Do Try
MapThreadActive:=True;synchronize(WWW);
Finally

End End;


 
DenisWW   (2004-01-28 01:06) [3]

кстати если удалить вызов ShellTreeView.SelectedFolder.PathName то всё работает- правда путь несуществующий


 
sniknik   (2004-01-28 01:10) [4]

> как видите я использую обьект ShellTreeView
визуальный компонент, шспользующий VCL? ну это ты зря в потоке. не threadsafe компонент.

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

и если используеш WaitFor (вызов и заверщение не показано но могу предположить) делай FreeOnTerminate:= false; и сам его после вызова освобождай, а то действительно возможен вариант, он завершится и освободится до вызова WaitFor(и тогда на ней ошибка). или не используй WaitFor.


 
DenisWW   (2004-01-28 08:59) [5]

Если заменить текст
If MapThreadActive and (MapThread<>Nil) Then With MapThread Do Begin
Terminate;
WaitFor;
End;
MapThread:=TMapThread.Create(False);

на

If MapThreadActive and (MapThread<>Nil) Then With MapThread Do Begin
Suspend;
End;
MapThread:=TMapThread.Create(False);

то всё работает !!!!!! вроде:)
Но вы понимаете , что поток ставится на паузу и существует в памяти, а мне нужно его удалить

соответственно вопрос:
Как из основного потока после вызова метода Terminate;
дождаться завершения доп. потока и освободить память


 
DenisWW   (2004-01-28 09:03) [6]

А также реально вычислить - закончился поток или в работе?


 
pasha_golub   (2004-01-28 09:28) [7]

Все операции с VCL в коде потока желательно оформлять через Synchronize


 
Dred2k   (2004-01-28 10:05) [8]

Полезно делать так:

Terminate;
if(not Suspended) then
WaitFor;


Причем это можно прямо в деструктор помещать, а потом просто поток разрушать через Free. Авторазрушением не пользуюсь.


 
DenisWW   (2004-01-28 12:18) [9]

Так я не хочу его засуспендить
я хочу подать сигнал в поток , что бы он как можно быстрее завершил себя и дождавшись этого запустить новую версию потока
соответсвенно правильно понимать :
1) Запущен ли поток(или он отработал и закрылся)
2) Если поток работает , закрыть его, подождать когда он закроется и запустить снова

Такое моё понимание потоков


 
Sandman25   (2004-01-28 12:22) [10]

Procedure TMapThread.Execute;
Begin With Form1 Do Try
MapThreadActive:=True;synchronize(WWW);
Finally
End End;

Выделенное жирным - тоже не thread-safe.
Лучше передавайте имя файла в конструкторе Вашего TThread.


 
DenisWW   (2004-01-28 12:29) [11]

Я уже давно так сделал
и всё работает только если я в конце потоку делаю Suspend;
а если хочу его закрыть и выждать закрытие WaitFor;
то глюки идууууут


 
Romkin   (2004-01-28 12:32) [12]

Намекаю: http://www.schevchenko.net.ru/ Супермаркет. Моделирование его работы потоками. Из Рихтера. Там все должно быть, и стартирование, и терминирование...


 
Polevi   (2004-01-28 12:50) [13]

hint
код поточной ф-ии не забывавай оборачивать в try except, иначе будет бяка


 
DenisWW   (2004-01-28 12:53) [14]

Ну есть мысль пользоваться одним потоком и просто его начинать с начало (с новыми парамметрами ) но это уже дело принципа


 
Digitman   (2004-01-28 13:05) [15]


> но это уже дело принципа


это дело далеко не принципа, а понимания преимуществ и недостатков такого подхода в конкретной среде и задаче


 
panov   (2004-01-28 13:14) [16]

1. Поток создается с FreeOnTerminate := False
2. В основном коде:
MyThread.Terminate;
MyThread.WaitFor;

3. Никаких Suspend в потоке (в данной задаче) не нужно.

4. Если поток находится в спящем состоянии, то необходимо выполнить

MyThread.Terminate;
MyThread.Resume;
MyThread.WaitFor;


 
DenisWW   (2004-01-28 13:34) [17]


> panov © (28.01.04 13:14) [16]
> 1. Поток создается с FreeOnTerminate := False
> 2. В основном коде:
> MyThread.Terminate;
> MyThread.WaitFor;
>
> 3. Никаких Suspend в потоке (в данной задаче) не нужно.
>
> 4. Если поток находится в спящем состоянии, то необходимо
> выполнить
>
> MyThread.Terminate;
> MyThread.Resume;
> MyThread.WaitFor;


я это и делаю
происходит трабл как я писал выше
Проблемма такая через несколько быстрых циклов XP-начинает работать неправильно - но без явной ошибки
а вот Win98 даёт ошибку явно:
System error: Code 6
Неверный дескриптор


 
DenisWW   (2004-01-28 13:37) [18]

Тоесть попытка послать тормоз потоку и подаждать пока он завершится и тутже вызвать новую версию потока
If MapThreadActive and (MapThread<>Nil) Then With MapThread Do Begin
Terminate;
WaitFor;
End;
MapThread:=TMapThread.Create(False);

при достаточно быстром повторе даёт сбой


 
panov   (2004-01-28 13:39) [19]

при достаточно быстром повторе даёт сбой

При каком повторе?
WaitFor означает, что следующий оператор у тебя не выполнится, пока не завершится поток.

Кстати, забыл, что поток тебе нужно уничтожить вручуню. Т.е. после WaitFor нужно выполнить MyThread.Free;


 
DenisWW   (2004-01-28 13:40) [20]

Повтор я имею ввиду - скорость повтора при удерживании клавиши


 
DenisWW   (2004-01-28 13:41) [21]

я уничтожаю поток таким образом
Procedure TMapThread.DoTerminate;
Begin
MapThread.FreeOnTerminate:=True;
MapThreadActive:=False;
End;


 
DenisWW   (2004-01-28 13:44) [22]

procedure TForm1.ShellTreeView1Change(Sender: TObject; Node: TTreeNode);
begin
If MapThreadActive and (MapThread<>Nil) Then With MapThread Do Begin
Terminate;
WaitFor;
End;
MapThread:=TMapThread.Create(False);
end;
Поток вызывается при смене директории в обьекте ShellTreeView папка Samples


 
panov   (2004-01-28 14:02) [23]

Что такое DoTerminate и что такое MapThreadActive ?
Если MapThreadActive - глобальная переменная, то обрати внимание на работу с этой переменной.


 
csr_   (2004-01-28 14:05) [24]

Ты потоки не синхронизируешь - от сюда глюки !!!


 
DenisWW   (2004-01-28 14:30) [25]


> csr_ (28.01.04 14:05) [24]
> Ты потоки не синхронизируешь - от сюда глюки !!!

обьясни


 
DenisWW   (2004-01-28 14:48) [26]


> Что такое DoTerminate и что такое MapThreadActive ?
> Если MapThreadActive - глобальная переменная, то обрати
> внимание на работу с этой переменной.


DoTerminate это:
Generates an OnTerminate event.

procedure DoTerminate; virtual;

Description

DoTerminate calls the OnTerminate event handler, but does not terminate the thread.

По русски :
Процедура которая выполняется когда поток закрывается

________________________________________________________

MapThreadActive булевая глобальная переменная которая которая в начале execute устанавливается в True , а в конце OnTerminate в False - я думаю , что это мне поможет понять запущен ли поток


 
DenisWW   (2004-01-28 14:58) [27]

стынет вопрос то!!!


 
sniknik   (2004-01-28 15:36) [28]

отвечающим то надоело. ответы были проигнорированы.
(ну ладно я кратко, и может непонятно, написал но уж Панов вообше все по полочкам разложил. а толку?)


 
AKul   (2004-01-28 15:45) [29]

to denisWW © :
Проблема в том, что FreeOnTerminate:=true выполняется в DoTerminate!
Если взглянуть на код TThread.ThreadPorc (это то, что Windows вызовет после CreateThread):
try
Thread.Execute;
finally
FreeThread := Thread.FFreeOnTerminate;// смотрим сюда
Result := Thread.FReturnValue;
Thread.FFinished := True;
Thread.DoTerminate; // потом сюда
if FreeThread then Thread.Free; // и наконец сюда
EndThread(Result);
end;
Думаю теперь стало ясно?
Так сделано потому, что уже нет возможности возобновить выполнение метода Execute (он завершился)!


 
DenisWW   (2004-01-28 20:29) [30]

Поправка существенная но ....
к сожалению она не исправила ничего


 
DenisWW   (2004-01-28 20:51) [31]

Почему этот текст правильный
If MapThreadActive and (MapThread<>Nil) Then With MapThread Do Begin
Terminate;
WaitFor;
MapThread.Free;
End;
MapThread:=TMapThread.Create(True);
MapThread.Resume;

а этот неправильный ???????????
If MapThreadActive and (MapThread<>Nil) Then With MapThread Do Begin
Terminate;
WaitFor;
End;
MapThread:=TMapThread.Create(True);
MapThread.FreeOnTerminate:=True;
MapThread.Resume;


 
panov   (2004-01-28 21:44) [32]

>DenisWW © (28.01.04 20:51) [31]

Потому что поток у тебя не уничтожается во втором случае...


 
sniknik   (2004-01-28 22:00) [33]

panov © (28.01.04 21:44) [32]
поправка.
он же его(этот код) гонит постоянно как бы в цикле (гдето писал о нажатии клавиши, и удержании)
наоборот он во втором случае уничтожится (иногда) раньше чем вызов WaitFor произойдет.
перепиши код в нормальном виде яснее будет (вот за это нелюблю With)
второй "нормализованный" вариант

> а этот неправильный ???????????
begin //типа кусок кейпрессед
If MapThreadActive Then Begin
MapThread.Terminate; //на завершение и уничтожение!!!! см. FreeOnTerminate
MapThread.WaitFor; //обращение к возможно успевшему самоуничтожится обьекту MapThread !!!ошибка!!!ошибка!!!ошибка!!!
End;
MapThread:=TMapThread.Create(True); //начинается отсюда
MapThread.FreeOnTerminate:=True; //самоуничтожение!!!
MapThread.Resume; //запустили
MapThreadActive:= true;
end.


 
panov   (2004-01-28 22:17) [34]

>sniknik © (28.01.04 22:00) [33]

Сорри, но если FreeOnTerminate=True, то WaitFor не сработает...


 
sniknik   (2004-01-28 22:35) [35]

panov © (28.01.04 22:17) [34]
а обрашение к методу будет? думаю да. а там нет ничего, уже.


 
AKul   (2004-01-29 09:35) [36]


> DenisWW © (28.01.04 20:29) [30]
> Поправка существенная но ....
> к сожалению она не исправила ничего

Освобождайте поток сами (FreeOnTerminate:=false), после вызова WaitFor.

Зачем Вам в цикле постоянно создавать и завершать поток?
Логичнее было б, если бы поток 1 раз создавался, а цикл крутился внутри его (да и к тому же не будет попросту расходоваться процессорное время). А управлять циклом внутри этого потока Вы всегда сможете из любого другого потока.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.02.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.011 c
1-29438
Apache
2004-01-18 03:10
2004.02.10
Ссылка на файл


1-29442
Grinder
2004-01-30 22:31
2004.02.10
как определить находится ли курсор над формой или нет?


6-29515
ruffest
2003-12-02 22:09
2004.02.10
Wake On Lan


7-29636
DNT
2003-11-05 12:03
2004.02.10
Скрытый запуск приложения.


3-29258
NoName
2004-01-18 15:59
2004.02.10
Перемещение по Gridu





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