![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вызов процедуры в другом потоке с параметрами [Win2k, WinXP]
__DATA__ © (2006-03-01 11:27:00)Как вызвать процедуру в другом потоке с параметрами?
Делаю так :
procedure TForm1.Button1Click(Sender: TObject);
procedure WBNavigate(URL: String);
begin
URL := URL;
end;
var
s: String;
c: Cardinal;
begin
s := 'www.rambler.ru';
CreateThread(nil,SizeOf(s),@WBNavigate,@s,0,c);
end;
Но в процедуре WBNavigate переменная URL = '', хотя в ней должно было быть 'www.rambler.ru'. Почему значение переменной в процедуру не передается?
И еще как передать в поточную процедуру несколько параметров?
GrayFace (2006-03-30 10:30:00) [1]Передавай адрес record'а, в котором все это содержится. Или включай их в наследника TThread.
fobos (2006-03-27 10:32:00) [2]Народ ... я хотел бы у Вас поитересоваться, ктонит знает как вызвать процедуру с неколькими параметрами к примеру MyProc(mems:TStringList;login:string;fp:conf;crypt:Word;path,ver:string); где fp - это тип используемый программой ... ?
GrayFace (2006-03-06 15:35:00) [3]Резницы нет только если сразу с PChar'ом работать. А если вначале сделать строку, потом выделить память и переписать ее туда, то выделение и переписывание можно сэкономить.
Leonid Troyanovsky (2006-03-06 15:20:00) [4]
> GrayFace © (06.03.06 13:14) [29]
> Еще экономия времени на выделение и копирование памяти!
Нет никакой экономии. То, что оно делается неявно -
не означает, что выделения и освобождения нет.
--
Regards, LVT.
GrayFace (2006-03-06 13:14:00) [5]Еще экономия времени на выделение и копирование памяти! =) А мне наоборот нравятся подобные хитрости.
Делал я ради интереса отложенную загрузку на Delphi - вот это вышло самое то - оптимально, компактно, красиво и абсолютно нечитаемо! Хотя, учитывая задачу, читаемость вышла вполне приемлемая.
Leonid Troyanovsky (2006-03-06 09:35:00) [6]
> GrayFace © (04.03.06 15:01) [27]
> Финализация происходит в конце WBNavigate. В момент "<--
> 1" в переменную s записывается переданная строка без увеличения
> счетчика ссылок (остается 1),
В переменную s просто записывается указатель (на раннее выделенную,
но неуничтоженную строку). Поэтому и не происходит никаких изменений
в ранее распределенном блоке, содержащем количество распределенных
байт, длину и счетчик ссылок, да и в самой строке).
Также понятно, как удается обмануть финализацию, бо наличие nil в
s интерпретируется как отсутствие у строки распределенного блока
размером 12+length.
Т.е., механизм этого стал понятен после [21] (зуб спасен ;)
Но, в общем-то, понятно, что этот способ ничем не лучше простого
GetMem с последующим освобождением в функции потока.
Бо, экономия пары строк кода ведет к полной его нечитаемости.
--
Regards, LVT.
GrayFace (2006-03-04 15:01:00) [7]> Leonid Troyanovsky © (03.03.06 19:11) [25]
> Ну, да. Рабочим его делает отложенная финализация,
> сроки наступления которой еще требуют уточнений.
Финализация происходит в конце WBNavigate. В момент "<-- 1" в переменную s записывается переданная строка без увеличения счетчика ссылок (остается 1), а при завершении WBNavigate строка финализируется, т.к. на нее указывает переменная s.
Fay (2006-03-03 19:14:00) [8]2 begin...end © (03.03.06 19:05) [24]
> См. код System.ThreadWrapper
Смотрел. Не понял 8(.
Leonid Troyanovsky (2006-03-03 19:11:00) [9]
> begin...end © (03.03.06 18:47) [21]
> Что некорректно? Пользоваться рабочим указателем?
..
> Этот пример не соответствует [8]. В [8] предотвращается
> финализация строки.
Ну, да. Рабочим его делает отложенная финализация,
сроки наступления которой еще требуют уточнений.
Для трех строчек кода неплохой результат, но для пятницы - тяжело.
Ладно, считай - зуб ты отстоял :)
--
Regards, LVT.
begin...end (2006-03-03 19:05:00) [10]> Fay © (03.03.06 18:59) [23]
В организации обработки исключений, например. См. код System.ThreadWrapper.
Fay (2006-03-03 18:59:00) [11]2 begin...end © (03.03.06 18:47) [21]
> И дело не только в IsMultiThread.
А в чём ещё?
Leonid Troyanovsky (2006-03-03 18:48:00) [12]
> Fay © (03.03.06 18:40) [20]
> > От чего же?
> Да хоть в файле проекта
Самый, IMHO, верный способ забыть о чем-то,
положить именно это туда.
Однако, замечание принято.
Хендлы надо закрывать всегда, а особенно - в учебных целях.
--
Regards, LVT.
begin...end (2006-03-03 18:47:00) [13]> Leonid Troyanovsky © (03.03.06 18:07) [16]
> Потому, как некорректно.
Что некорректно? Пользоваться рабочим указателем?
> Рассмотрим следующий случай: ...
Этот пример не соответствует [8]. В [8] предотвращается финализация строки.
> Fay © (03.03.06 18:40) [20]
Уже неоднократно говорилось, что в Delphi следует использовать BeginThread вместо CreateThread. И дело не только в IsMultiThread.
Fay (2006-03-03 18:40:00) [14]2 Leonid Troyanovsky © (03.03.06 18:37) [19]
> От чего же?
Да хоть в файле проекта
Leonid Troyanovsky (2006-03-03 18:37:00) [15]
> Fay © (03.03.06 18:16) [18]
> Дык IsMultithread может и не упоматься именно в этом участке
> кода.
От чего же?
Для таких сочетаний как String & CreateThread оно вовсе не лишне.
--
Regards, LVT.
Fay (2006-03-03 18:16:00) [16]2 Leonid Troyanovsky © (03.03.06 18:11) [17]
> Никто не говорил и про IsMultithread.
Дык IsMultithread может и не упоматься именно в этом участке кода.
Leonid Troyanovsky (2006-03-03 18:11:00) [17]
> Fay © (03.03.06 17:48) [14]
> Никто, кажется, не упомянул, что CreateThread - функция.
Никто не говорил и про IsMultithread.
Но, в данном случае, не до утечки хендлов.
--
Regards, LVT.
Leonid Troyanovsky (2006-03-03 18:07:00) [18]
> begin...end © (03.03.06 17:13) [12]
> Зуб давать, конечно, не буду, но не вижу причин, по которым
> указанный способ в данном случае может быть нерабочим. Строка
> s при выходе из обработчика Button1Click не будет финализирована,
> и в поточную функцию передастся рабочий указатель на тело
> константной строки (плюс длину и счётчик ссылок, который
> -1). Почему бы этим указателем не воспользоваться внутри
> функции?
Потому, как некорректно.
Рассмотрим следующий случай:
function WBNavigate(P: PChar): LongInt; stdcall;
begin
Sleep(5000);
MessageBox(0, p, nil, 0);
end;
procedure TForm1.Button1Click(Sender: TObject);
var s: String;
с: DWord;
begin
s := IntToStr(GetTickCount);
CreateThread(nil, 0, @WBNavigate,Pointer(s),0,с);
end;
Т.е., если нажать несколько раз в течении 5 сек, мы получим
несколько боксов с _одним_ временем (каким?).
Ну, а про изменение s после CreateThread и говорить не стоит.
Если же речь о константе, то ее и не следует рядить в стринг.
--
Regards, LVT.
begin...end (2006-03-03 17:56:00) [19]> Fay © (03.03.06 17:46) [13]
> При выходе - это после выхода?
При выходе -- это в процессе выхода.
> А до какого момента?
В данном случае (в случае константной строки) -- до момента завершения процесса (причём даже если убрать последнюю строку обработчика из [8]). А в других случаях (например, когда счётчик ссылок у строки, объявленной в обработчике, будет равен 1, а не -1) -- до момента завершения функции потока, вероятно.
Тем не менее, просьба не считать меня приверженцем способов типа [8].
Fay (2006-03-03 17:48:00) [20]Никто, кажется, не упомянул, что CreateThread - функция.