Форум: "Основная";
Текущий архив: 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);
А world_sort сортируем tL.
tL.Assign(Form1.Memo2.Lines);
После сортировки копируем 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)
Да вообщем-то аргументы весьма просты и даже глубоко копать не надо. Рассмотрим затронутую тут тему, добавление строки в TMemoMemo1.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.01 c