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

Вниз

Мастера, не могу правильно выйти из потока, делаю:   Найти похожие ветки 

 
Yuraz ©   (2002-04-01 17:32) [0]

procedure TTestThread.Execute;
begin
FreeOnTerminate:=true; // как сказанно, для прекращения потока

.....код......

end;

В результате по выходу из программы или повторного использования программы пишется WinError, ошибка 1400
Что доделать? В хелпе больше ничего не нашёл по выходу :(


 
Виктор Щербаков ©   (2002-04-01 17:36) [1]

Там где у тебя
.....код......,
нужно время от времени проверять свойство Terminated, и если оно True, то выходить из метода.


 
panov ©   (2002-04-01 17:47) [2]

Как правило, внутри Execute используется конструкция:

while not Terminated do
begin
//...
//твой код
if Terminated then Break;
end;


 
Yuraz ©   (2002-04-01 17:50) [3]

begin
FreeOnTerminate:=true;
for i:=1 to 200000 do begin
if Terminated then Break;
....код....
//вызов др процедуры из похожего модуля с for как здесь
proc_world;
end;
end;

может в proc_world тоже надо FreeOnTerminate:=true;?


 
panov ©   (2002-04-01 17:55) [4]

>Yuraz © (01.04.02 17:50)
Нет, в другой процедуре не надо.
У потока есть еще метд WaitFor.
Обрати на него внимание.


 
Yuraz ©   (2002-04-01 17:56) [5]

Только сейчас увидел, у меня программа по завершению работы вычислений, не завершает свою работу, а без конца добавляет и добавляет (уже пустые ) ячейки в StringGrig, хотя всё считается быстро и не заметно что комп нагружен.

После совета panov, ошибка исчезла, но вот без конца работает :(


 
panov ©   (2002-04-01 18:15) [6]

приведи код Execute и основные моменты твоей процедуры.


 
Yuraz ©   (2002-04-01 18:32) [7]

Не знаю, может слишком сокращённо, но суть в том, что после завершения процесса выполнения работы программы, сама программа не завершает работу, и работает дальше, т.е. цикл i не завершается.


procedure TTestThread.Execute;
begin
while not Terminated do //многопоточность

begin
for i:=1 to 1000000 do
begin
if Terminated then break;
Form1.memo2.add(случайный текст);
end;
end;

Form1.Memo2.Visible:=True;
flag1:=true; // разрешено печатать и в html
world_sort; // это отдельная проц. из др. модуля, сортировка memo2 по алфавиту

end;
end.



 
Yuraz ©   (2002-04-01 18:41) [8]

PS,

world_sort; // это отдельная проц. из др. модуля, сортировка memo2 по алфавиту

без неё так же не останавливается, т.е. дело не в ней :)


 
Набережных С.   (2002-04-01 20:18) [9]


> Form1.memo2.add(случайный текст);

Что, вот так прям и написано, без Synchronize? Или просто сократил? А ОС, видимо, 9х? Поставь в OnCloseQuery главной формы TestThread.Terminate.


 
Набережных С.   (2002-04-01 20:49) [10]

Насчет Synchronize не обращай внимания, разобрался, мне просто не случалось так делать.


 
panov ©   (2002-04-02 06:46) [11]

Из приведенного кода видно, что ты работаешь с объектами в основном потоке из дополнительного.
В таком случае необходимо использовать метод Synchronize:
В Execute пишем:
tL: TStringList; определяем в секциях определения класса TTestThread

begin
...
begin
for i:=1 to 1000000 do
begin
if Terminated then break;
// Form1.memo2.add(случайный текст);
Synchronize(Upd1);
end;
end;

...
world_sort;
Synchronize(Upd2);

tL.Assign(Form1.Memo2.Lines);
А world_sort сортируем tL.
После сортировки копируем tL.Strings в Form1.Memo2.Lines, но при этом используем снова метод Synchronize:
Synchronize(Upd2);

В Upd1 и Upd2 пишем соответственно:

procedure TTestThread.Upd1;
begin
Form1.memo2.add(случайный текст);
end;


procedure TTestThread.Upd2;
begin
Form1.memo2.Lines.Assign(tL);
end;


В конструкторе класса пишем
Inherited Create(True);
tL := TStringList.Create;
FreeOnTerminate := True;
Resume;


В деструкторе, соответственно
tL.Free;

При необходимости запуска потока:

TTestThread.Create(True); // с параметрами, определенными у тебя.

Все должно работать.

Смысл изменений в том, что из отдельного потока работать с объектами, определенными в основном потоке, нужно через защищенные методы, например, через Synchronize.


 
Yuraz ©   (2002-04-02 16:32) [12]

Александр спасибо! Только сел за инет, разбираюсь.


 
Набережных С.   (2002-04-02 16:43) [13]


> panov © (02.04.02 06:46)

Для добавления в TMemo не нужен Synchronize.


 
Digitman ©   (2002-04-02 18:12) [14]

>Набережных С.

Это почему же ? Позволь уж полюбопытствовать ...


 
Набережных С.   (2002-04-02 18:44) [15]

.
> Digitman © (02.04.02 18:12)

Да ради Бога! Все методы в конце-концов попадают в SendMessage, что и есть синхронизация. Для меня это тоже сюрприз - никогда не приходило в головку так сделать :)))


 
Alex Sudakov   (2002-04-02 19:33) [16]

Очень оригинально... Вот только вряд ли будет работать при наличии хотя бы двух потоков. При одновременном обращении к свойству объекта будет замечательный глюк...


 
Набережных С.   (2002-04-02 20:35) [17]


> Alex Sudakov (02.04.02 19:33)

Аргументируй. Какой глюк, в каком месте. Я что-то не вижу. Может, плохо смотрю? И, кстати, вчем видится оригинальность?


 
Suntechnic ©   (2002-04-03 04:04) [18]

>Набережных С. (02.04.02 20:35)
Да вообщем-то аргументы весьма просты и даже глубоко копать не надо. Рассмотрим затронутую тут тему, добавление строки в TMemo Memo1.Lines.Add("Test"); Наверное трудно не согласится, что в результате этой операции св-во Count у TStrings должно увеличиться. Т.к. VCL это не потоко безопасная библиотека, а инкремент счётчика это не атомарная операция, то возможна ситуация, что к этому св-ву попытается обратится кто-то другой(скажем тоже с целью увеличить его, добавить ещё одну строку) и последствия будут непредсказуемые. В св-ве Count будет находиться значение, которое не отражает действительного положения вещей и чем всё это закончится можно только догадываться. Заметь, я не влазил в дебри VCL и не просматривал весь код метода Add, а лишь взял то, что на поверхности. А если копнуть глубже, то найдёшь ещё десяток подобных мест.


 
dymka ©   (2002-04-03 08:20) [19]

если есть уверенность, что к элементу VCL доступ будет только из одного потока, то синхронизация ни к чему... при доступе из двух потоков и более нужно вызывать Synchronize дабы не было одновременного обращения к объекту (на самом деле одновременно и не может, если комп однопроцессорный, но возможно ситуация - когда когда отображение потока еще не закончено в VCL, а второй поток просто может завершить свое отображение)...
далее - вызов синхронизации немного ограничивает передачц параметров в основной поток - поэтому лучше использовать более продвинутые методы - критические секции итп...

procedure TTestThread.Execute;
begin
FreeOnTerminate := True;
for i:=1 to 1000000 do
begin
if Terminated then break;
Form1.memo2.add(случайный текст);
end;
end;

Form1.Memo2.Visible:=True;
flag1:=true; // разрешено печатать и в html
world_sort; // это отдельная проц. из др. модуля, сортировка memo2 по алфавиту

end;

должно работать... в своей прогамме при вызове
MyThread.Terminate;
свойство потока Terminated установится в True и поток завершится...


 
Digitman ©   (2002-04-03 08:26) [20]

>Набережных С.
Аргумент от <Suntechnic> - это раз.
Второе. В данном примере TMemo, конечно, создается не в контексте доп.потока (предположим, что - в контексте основном). Но, если конструктор TMemo (а чем он опаснее, в соответствии с твоими утверждениями, того же метода Lines.Add ?) поместить в доп.поток, то обработчик создаваемого ОС-окна (ассоциированного с Memo) будет в последствии так же вызываться системой в том же доп.потоке. И, представь себе, например, WndProc() этого окна будет вызвана в доп.потоке для обработки WM_PAINT (требуется перерисовка некоторой области окна, скажем, для отрисовки вновь добавленной строки). Обработчик в конечном итоге где-то в своем теле вызовет DrawText(), обращаясь к DC окна. И к этому же DC в этот же момент времени может обратится еще один поток того же процесса или kernel-leve-поток.. вот тебе и "глюк" на поверхность выполз)


 
Yuraz ©   (2002-04-03 10:26) [21]

Уважаемые мастера, может возмёте этот самый пример на
http://www.kirov.ru/~yura/delphi/d5_thread_exemple.zip
я сделал всё что советовал Александр (panov © (01.04.02 17:47)) , синхронизация не идёт, вопрос вот в чём,

begin
...
begin
for i:=1 to 1000000 do
begin
if Terminated then break;
// Form1.memo2.add(случайный текст);
Synchronize(Upd1);
end;
end;
...
world_sort;
Synchronize(Upd2);

tL.Assign(Form1.Memo2.Lines);А world_sort сортируем tL.
После сортировки копируем tL.Strings в Form1.Memo2.Lines, но при этом используем снова метод Synchronize:
Synchronize(Upd2);

В Upd1 и Upd2 пишем соответственно:

procedure TTestThread.Upd1;
begin
Form1.memo2.add(случайный текст);
end;

где написанно "случайный текст" код 2 раз повторять?

..сейчас просто не останавливается по окончанию работы, программа состоит из 4 модулей, делал в D5. Без многопоточности работала, но если цикл выставляешь большой, форма не реагирует на мышь (ну это как у всех обычных приложений).
Исправильный вариант можно скинуть на мой e-mail, я опубликую так же на сайте, ссылку здесь сразу бы да, да ещё статью бы на писал, на эту темку, для таких как я :)


 
Yuraz ©   (2002-04-03 10:27) [22]

Да, пример всего 4 кб в архиве.


 
Yuraz ©   (2002-04-03 10:30) [23]

//где написанно "случайный текст" код
Сорри, всё разобрался


 
REA   (2002-04-03 15:02) [24]

Когда работал с потоками (особенно в DLL) выяснил, что компоненты Delphi 5 как-то криво устроены (или у меня руки) - не всегда завершают поток (а должны - висло где-то в дебрях компонента на WaitFor), при чем при выходе из приложения ситуация обратная (т.е. если допустим по кнопке "стой" работает, то при выгрузке DLL не работает и наоборот). Никаких вызовов VCL из thread нету.
Перепробовал разные варианты с FreeOnTerminate и Terminated.
Поотом надоело - подстроился под это дело (усыплял поток Suspend и потом уже убивал).
Так вот в Delphi 6 этот код уже не работал. Пришлось переставлять строки местами и делать прочие шаманские пассы.
Сейчас вроде работает.


 
Набережных С.   (2002-04-03 17:54) [25]


> Suntechnic © (03.04.02 04:04)

Убедил. Я действительно плохо смотрел, зациклился на одном и упустил из виду Count. Однако для одного потока это вполне сработает.


> Digitman © (03.04.02 08:26)

Что с тобой? Перечитай посты. Я говорил именно о добавлении строк. Конструктор, точнее создание окна - совсем другая история. Окно должно быть создано в том же потоке, что и родительское. Рассматривать иной вариант просто не корректно. Я именно и зациклился на графическом контексте(а он здесь безопасен) и конкретной задаче. А в этой задаче Add пройдет "на ура", если одновременно не писать в Мемо из главного потока, но здесь-то это не делается.
Я чувствую в твоем посту какую-то врождебность. Это так?


> Yuraz © (03.04.02 10:26)

Смотри почту. Комментарии в тексте.


 
Digitman ©   (2002-04-03 18:13) [26]

>Набережных С.
Совершенно не так) Не стоит тревожиться)
Мне, возможно, лучше было было бы адресовать реплику-дополнение автору. Просто твое неудачное утверждение о thread-safety методов TMemo могло бы ввергнуть автора в последствии в заблуждение, что и конструктор TMemo с таким же успехом можно вызвать в доп.потоке.



 
Набережных С.   (2002-04-03 19:35) [27]


> Digitman © (03.04.02 18:13)

> Совершенно не так) Не стоит тревожиться)


Закрыто:)
Продолжая твою мысль стоит, наверное, пояснить, что первое обращение к методу, требующему хендл, должно производиться из потока родительского окна. Если, например, в дизайн-режиме установлено Visible = false(а так и сделано у автора вопроса), то необходимо обратиться из основного потока к свойству Handle до того, как это сделает дополнительный поток.



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

Текущий архив: 2002.04.15;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.015 c
3-46256
alexpsico
2002-03-25 19:06
2002.04.15
как сбросить кэш БДЕ на винт


3-46235
Rammst
2002-03-25 07:59
2002.04.15
Определение ... (HELP!!!)


3-46293
Serg!
2002-03-22 19:04
2002.04.15
ким образом можно динамически подгужать данные из select-запроса?


14-46492
VuDZ
2002-03-06 17:21
2002.04.15
2 Mike Goblin


1-46362
Maxim Homutov
2002-04-04 14:09
2002.04.15
Добрый день хотелось бы попросить о помощи