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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.005 c
1-46297
Сержик
2002-04-01 13:30
2002.04.15
Как вызвать диалог выбора папки?


14-46518
phantom2040
2002-03-06 15:10
2002.04.15
Округление в Delphi


1-46356
андрей Татуков
2002-04-04 10:46
2002.04.15
RichEdit.Print зависает (бесконечный Спулинг)


6-46470
viol-2
2002-02-04 11:14
2002.04.15
TWebBrowser


1-46432
Иван
2002-04-02 21:51
2002.04.15
отправка email





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