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

Вниз

bug в Thread   Найти похожие ветки 

 
Viman ©   (2004-04-26 08:57) [0]

Вот процедура потока в KOL, выставляющая флаг terminated.
Это странно выглядит, вы не находите :).
procedure TThread.Terminate;
begin
 TerminateThread(FHandle,0); <-- вот эта строка, такое вредительство :)
 FTerminated := True;
end;

В итоге проверять флаг Terminated в своей ExecProc уже нет никакого смысла - поток уже грубо убит и после этой строки больше просто не существует(без освобождения ресурсов, стека и т.п. и т.д.). Это ж просто не есть хорошо! У себя-то я поправлю, а кому, кстати, в таких случаях писать? Сразу Кладову или сюда? Или ещё кому?


 
Gandalf ©   (2004-04-26 21:02) [1]

Не совсем ясен смысл возмущения... Все нормально. Конечно проверять на Terminated после вызова Terminate не надо, так следует из логики и из кода - т.е. все ок.


 
csr ©   (2004-04-26 23:35) [2]

Дак разработчик КОЛа - оксяково написал - убери эту строку и работай как в VCL :)


 
SPeller ©   (2004-04-27 02:53) [3]

Флаг Terminated выставляется не для самого потока, который может проверять это значение, а для объекта, чтобы он знал что поток уничтожен. Поэтому ничего странного тут нет.


 
Viman ©   (2004-04-27 09:12) [4]

2 SPeller
Ну-да, ну-да, типа это не баг, а фича :)
А чтобы узнать в объекте работает поток или нет, так это нужно, например, хандл обнулять(что есть просто правильно), когда поток завершаешь или есть такая функция  GetExitCodeThread(hThread, lpExitCode). Когда поток ещё работает в lpExitCode вернется STILL_ACTIVE.

2 Gandalf
А что KOL становиться совершенно другой по смыслу библиотекой?
Я понимаю это, если для портирования приходиться сделать по-другому, но тут ..?. Тем более приходиться всё равно вводить подобную переменную самому, чтобы корректно выходить из процедуры потока(или удалять вызов TerminateThread(...)). Подобные же случаи просто усложняют жизнь. Неужели придется лезть в каждую процедуру и функцию - смотреть что там делается? По-моему это просто грабли, замедляющие разработку.


 
SPeller ©   (2004-04-27 10:59) [5]

Да, лезть в функцию и смотреть что она и как делает. Именно поэтому лично у меня всегда включена pas-версия. КОЛ — это не замена vcl, — это её альтернатива. А альтернатива не обязана всюду повторять vcl.


 
Viman ©   (2004-04-27 13:27) [6]

>csr
Конечно, я так и сделал.
>SPeller
Хм. Не понимаю всё это. Да, все прекрасно, замечательная библиотека, много хорошего. Но такое отношение, по-моему, просто необъективно и попахивает фанатизмом, а это не всегда правильно - снисходительно относиться начинашь. Проще тогда на API писать сразу  - заведомо известно как себя поведет. А насчет времени написания ?.. Так за время выискивания и обхода "фич" в библиотеке можно с успехом и на API шаблон написать, который потом можно многократно использовать.
Вроде библиотеки и создаются для ускорения разработки(ну, конечно, знать-то их необходимо, но не до последнего же байта), а не наоборот.

> all
Все спорите-спорите, я просто глаза отрываю на баг. :)
Кстати, видели деструктор TThread? Нет, посмотрите. Там вызывается как раз Terminate. Одни противоречия. Да, конечно, пользуйтесь, говорите, что все замечательно. Но, если в проге будут периодически создаваться и удаляться потоки, то такая прога именно уже из-за такого terminate будет терять ресурсы, причем далко не 100 байт(стек в среднем ~500Кб-1Мб, ещё что-нибудь). Прочитайте лучше в Win API help про TerminateThread.
Это функция только для исключительных ситуации, а не "нормального" завершения потока.


 
Gandalf ©   (2004-04-28 13:10) [7]

Part I
1) KOL отличается от VCL по архитектуре построения - все сделано по принципу "ничего лишнего" - порой в ущерб удобству.
2) Аналогии между KOL и VCL есть - их много, но не они не идентичны.
3) В некотором смысле KOL переходной этап между VCL и API, без визуально мусора, который попадает в код. Для разработки есть MCK.
4) MCK это НЕ VCL
5) MCK это даже НЕ KOL

Part II

Про ресурсы и потоки - "брехня товарищи", извиняюсь за выражение - это легко увидеть на практике. Создаем толпу потоков и потом их мочим. И уходим в нулях. Нет утечек...


 
Viman ©   (2004-04-29 16:37) [8]

2 Gandalf
Про part I. Ранее, я имел ввиду только то, что KOL все равно несет(перенимает) много смысловой нагрузки от VCL(имена, методы). И мое мнение было таким всегда: если уж повторяешься, то повторяться нужно в тему. Ведь не понравиться, к примеру, когда в меню программы на действие "Закрыть документ" она вам его ещё и удалит дополнительно. По-моему никто это за "фичу" даже не посчитает. Для таких вещеё надо давать просто другие имена и все будет намного легче, например, AbortThread(Execute)- просто и понятно, да и граблей(без лазанья по функциям) меньше.

> Part II
>
> Про ресурсы и потоки - "брехня товарищи", извиняюсь за выражение
> - это легко увидеть на практике. Создаем толпу потоков и
> потом их мочим. И уходим в нулях. Нет утечек...

И на какой практике вы это видели? И сколько это "толпа"? 10-50?
Уходите в нулях? Это при завершении программы? Там-то конечно - винда все освободит. Профилировщиками пользовались конечно?
Чтобы не быть голословным вот код теста:
procedure TForm1.Button1Click(Sender: PObj);
var thr: PThread;
begin
while not NeedTerminate do
begin
  Applet.ProcessMessages;
  thr:=NewThread;
  if (thr^.Handle=0) or (thr^.Handle=INVALID_HANDLE_VALUE) then
  begin
    MessageBox(Form1.Form.Handle, PChar(SysErrorMessage(GetLastError)),
     "error!", 0);
     exit;
  end;
  thr.OnExecute:= ExecProc;
  thr.AutoFree:= true;
  thr.Resume;
  Sleep(0);
  thr.Terminate;
//   thr.Free; можно по вкусу Terminate заремарить, а Free
              разремарить, только медленней будет, а результат тот же...
  thr:=nil;
  i:= i+1;
  Label1.Caption:= Int2Str(i);
end;
NeedTerminate:= false;
end;

procedure TForm1.Button2Click(Sender: PObj);
begin
NeedTerminate:= true;
end;

function TForm1.ExecProc(Sender: PThread): Integer;
begin
 While true do;
 result:=0;
end;

Как вы думаете, сколько раз успевает создаться и "замочиться" поток? У меня на win2k около 2000 раз. Это ещё и от объема памяти и т.п. зависит. Какой результат? Прога встала на 100%! Кто не верит сообщениям, своим рукам и глазам - может профилировщиком воспользоваться. Цикл попыток создания может и дальше продолжаться, вот только уже ничего не получиться создать. А вы про 0... Только не надо говорить, что мол далеко не в каждой проге столько раз потоки создаваться - убиваться будут. Тут-то всегда только первичный(главный) и один вторичный. Дело времени, обёма памяти, да и принципа...
Все могут попробовать, поэсперементировать, тест наипростейший.
Так что это - грабли, баг или очередная "фича"? Каково ваше мнение, читающий?


 
Gandalf ©   (2004-04-29 23:06) [9]

1) Я никогда не говорил - что не осответсвия это хорошо, это не так.

2) Я проверял создав 1000 потоков - думаю хватает для теста. Естестно наблюдал утечку не опасля. Посмотрел и ваш вариант - ну и что? Утечки потоков нет - есть утечка дескрипторов, но это лишь потому что вы проводите тождество между Terminate и Free - легко их приравняв. Надо использовать Free - как я говорю утечка в нуле  - я своим глазам верю. Сорри. KOLnMCK 1.91 Delphi 7 WinXP SP1 RUS


 
Viman ©   (2004-04-30 09:11) [10]

Я не приравнивал Terminate и Free. Посмотрите пример повнимательнее, там есть комментарий на эту тему. Пробуйте использовать Free, результат все равно будет тот же. Да и ещё в destroy handle сравнивается с INVALID_HANDLE_VALUE(равным -1). Это ж неверный handle для файлов, а для потоков, насколько я помню неверное значение = 0. Но это бестолку, правка этого тоже не помогает.
Признаю, что утечки непосредственно памяти нет(глянул что создать не может и упокоился :)). Но ведь согласно пословице: хрен редьки не слаще. По-моему, такую прогу нельзя назвать достойной настоящего применения, только для "песочника" - она в принципе не может считаться отличной или стабильной. Я уверен ещё много таких "сюрпризов" можно найти в библиотеке... Ни о каких серверных задачах, активно создающих потоки, которые будут закрываться во время работы, с таким подходом и речи быть не может.
Вот все мы периодически обижаемся на то, что народ лениться, что программы вечно наполовину сырые и недоделанные, а Вы, многими кстати уважаемый(и к вашему мнению прислушиваются, особенно новички), сейчас сами даете повод так расслабляться - мол это ничего, это можно, подумаешь хандлы потоков не освобождаются - так их же много! Как-то все это не очень выглядит...


 
Gandalf ©   (2004-04-30 11:43) [11]

1) INVALID_HANDLE_VALUE конечно должен быть =0, это баг но его исправят.
2) Вернемся к теме, конкретно ваш пример не приводит:
 а) к сбоям в программе и системы в целом,
 б) к зависанию программы и системы в целом
 в) исчерпанию ресурсов (отсутсвуют какие либо утечки)
При условии что используется Free.
Проверял лично.

У вас происходит нечто из выше приведенных проблем в данном конкретном случаи? Что вас не устраивает?


 
Viman ©   (2004-04-30 13:47) [12]

Я уж специально ещё раз только Free оставил, Terminate заремарил.
Заменил в KOL в деструкторе(и asm, и pas-версиях) INVALID_HANDLE_VALUE на 0. Запустил. Результат то же. ~2000 итерации и выдает мессагу. Неужели у вас НЕ ТАК ?! Проблема только в том, что больше не может создаться поток или это не проблема? KOLnMCK 1.91 Delphi 5 Win2k SP4 RUS, пробовал и на 98

Все меня устраивает. Особенно когда можно удобно и эффективно(размер файла для меня много значит, вот я и здесь) работать. А чтобы было и то и другое в данном случае, давно пришлось перенести VCL-ый вариант потока и кое-что другое с небольшими поправками под KOL и нет проблем, никаких. А тут я просто спорю (на то и форум), ищу истину, как говориться. :) Чтобы другие знали...


 
Gandalf ©   (2004-04-30 16:48) [13]

У меня не так - я на пол часа поставил - все нормально пахало...


 
Владимир Кладов   (2004-04-30 17:17) [14]

В приведенном примере в цикла начинают создаваться потоки. Не уничтожаясь. Вы что же думаете, система, в состоянии запустить более 2000 потоков на одном процессе?


 
Владимир Кладов   (2004-04-30 17:37) [15]

Вот исправление. Только не надо рамахивать ничем. Посмотрите внимательно.

procedure TForm1.Button1Click(Sender: PObj);
var thr: PThread;
begin
while not NeedTerminate do
begin
 Applet.ProcessMessages;
 thr:=NewThread;
 if (thr^.Handle=0) or (thr^.Handle=INVALID_HANDLE_VALUE) then
 begin
   MessageBox(Form1.Form.Handle, PChar(SysErrorMessage(GetLastError)),
    "error!", 0);
    exit;
 end;
 thr.OnExecute:= ExecProc;
 ///////////thr.AutoFree:= true;
 Inc( NThreads );
 Label1.Caption:= Int2Str( NThreads );
 thr.Resume;
 Sleep(0);
 //thr.Terminate;
 thr.Tag := 1;
 while thr.Tag < 2 do Sleep( 0 );
 thr.Free; //&igrave;&icirc;&aelig;&iacute;&icirc; &iuml;&icirc; &acirc;&ecirc;&oacute;&ntilde;&oacute; Terminate &ccedil;&agrave;&eth;&aring;&igrave;&agrave;&eth;&egrave;&ograve;&uuml;, &agrave; Free
//              &eth;&agrave;&ccedil;&eth;&aring;&igrave;&agrave;&eth;&egrave;&ograve;&uuml;, &ograve;&icirc;&euml;&uuml;&ecirc;&icirc; &igrave;&aring;&auml;&euml;&aring;&iacute;&iacute;&aring;&eacute; &aacute;&oacute;&auml;&aring;&ograve;, &agrave; &eth;&aring;&ccedil;&oacute;&euml;&uuml;&ograve;&agrave;&ograve; &ograve;&icirc;&ograve; &aelig;&aring;...
 //thr:=nil;
 Dec( NThreads );
 Label1.Caption:= Int2Str( NThreads );
end;
NeedTerminate:= false;
end;

procedure TForm1.Button2Click(Sender: PObj);
begin
 NeedTerminate := TRUE;
 Form.Close;
end;

function TForm1.ExecProc(Sender: PThread): Integer;
begin
 While Sender.Tag = 0 do Sleep( 0 );
 Sender.Tag := 2;
 result:=0;
end;


 
Delphi5.01 ©   (2004-05-11 16:47) [16]

Kruto, priatno chitat diskusiu mejdu profesionalami :-)) Mnogo chemu nauchishsa, peoimosh chego ne nado dealat, cho nado ispravlat :-)))
Bravo!


 
Игорь Шевченко ©   (2004-05-14 13:40) [17]


> Вы что же думаете, система, в состоянии запустить более
> 2000 потоков на одном процессе?


Да. До тех пор, пока размер стека позволяет.

"The number of threads a process can create is limited by the available virtual memory. By default, every thread has one megabyte of stack space. Therefore, you can create at most 2028 threads. If you reduce the default stack size, you can create more threads. "


 
Vladimir Kladov   (2004-05-14 14:05) [18]

Вот именно. На 2028 система и сказала, что больше потоков создать не может. А поток должен отдавать свои слайсы основному потоку как минимум, чтобы тот имел возможность заняться удалением потока. Просто так главный поток управление не получит.


 
Игорь Шевченко ©   (2004-05-14 15:59) [19]

Vladimir Kladov   (14.05.04 14:05)


> На 2028 система и сказала, что больше потоков создать не
> может.


Уменьши размер стека в 16 раз в опциях проекта :)


> А поток должен отдавать свои слайсы основному потоку как
> минимум, чтобы тот имел возможность заняться удалением потока.
>


Вообще-то поток и сам может удалиться, вызвав ExitThread.


> Просто так главный поток управление не получит.


Получит, при диспетчеризации.

Впрочем, мы уже здорово в offtopic ушли.

С уважением,



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

Форум: "KOL";
Текущий архив: 2004.12.26;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.045 c
14-1102493504
PRM
2004-12-08 11:11
2004.12.26
Чем открыть файл xmlsdkdoc.msm


1-1102683452
Bobby Digital
2004-12-10 15:57
2004.12.26
Line


6-1097733021
Dr. Genius
2004-10-14 09:50
2004.12.26
TDriveType, dtFixed, dtNetWork


1-1102847589
Frozzen
2004-12-12 13:33
2004.12.26
Копирование буфера Move


1-1102587453
Dmitrij_K
2004-12-09 13:17
2004.12.26
DLL





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