Форум: "WinAPI";
Текущий архив: 2006.07.02;
Скачать: [xml.tar.bz2];
ВнизВызов процедуры в другом потоке с параметрами Найти похожие ветки
← →
__DATA__ (2006-03-01 11:27) [0]Как вызвать процедуру в другом потоке с параметрами?
Делаю так :
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". Почему значение переменной в процедуру не передается?
И еще как передать в поточную процедуру несколько параметров?
← →
isasa © (2006-03-01 11:46) [1]Функция должна быть
TThreadFunc = function (p : pointer) : longint; stdcall;
← →
isasa © (2006-03-01 11:51) [2]И еще как передать в поточную процедуру несколько параметров?
Поток
type
TCheckURL = record
msgWnd : HWND;
idURL,idPrx : integer;
URL: string;
Proxy: string;
Port: integer;
login : string;
pass : string;
Result : integer;
bufLen : Longword;
Header, Body : string;
end;
pURLs = ^TCheckURL;
function CheckURL(p : pointer) : longint; stdcall;
var cURL : pURLs;
...
begin
...
cURL:=pURLs(p);
вызов
var
cURL : TCheckURL;
...
cURL.login := login.Text;
cURL.Pass := pass.Text;
...
hThread:=CreateThread(nil, 0, @CheckURL, @cURL, 0, ThreadID);
← →
__DATA__ (2006-03-01 11:56) [3]procedure TForm1.Button1Click(Sender: TObject);
function WBNavigate(P: Pointer): LongInt; stdcall;
var
URL: String;
begin
URL := String(p);
end;
var
c: Cardinal;
s: String;
begin
s := "www.rambler.ru";
CreateThread(nil,SizeOf(s),@WBNavigate,@s,0,c);
end;
Теперь в URL какая-то бяка передается ... :(
Теперь
← →
isasa © (2006-03-01 12:04) [4]А строку через PChar?
← →
__DATA__ (2006-03-01 12:16) [5]function WBNavigate(P: Pointer): LongInt; stdcall;
var
pc: PChar;
begin
pc := p;
MessageBoxA(0,pc,pc,0);
end;
Тоже бяка! :(
и
function WBNavigate(P: Pointer): LongInt; stdcall;
var
pc: PChar;
begin
pc := PChar(p);
MessageBoxA(0,pc,pc,0);
end;
Тоже!
← →
isasa © (2006-03-01 12:23) [6]procedure TForm1.Button1Click(Sender: TObject);
function WBNavigate(P: Pointer): LongInt; stdcall;
...
var
c: Cardinal;
s: String; <--------------- вот тут переменную создали в стеке
begin
s := "www.rambler.ru";
CreateThread(nil,SizeOf(s),@WBNavigate,@s,0,c); <----вот тут запустили поток
end; <---------- вот тут переменной s: String; уже нет, а поток еще есть, или нет?
Объявить ее как поле класса (public, private - по вкусу)
← →
__DATA__ (2006-03-01 12:26) [7]Пасиб, заработался... :)
← →
GrayFace © (2006-03-03 11:05) [8]Строки тоже можно передавать:
function WBNavigate(P: Pointer): LongInt; stdcall;
var
URL: String;
begin
pointer(URL) := p; <-- 1
end;
procedure TForm1.Button1Click(Sender: TObject);
var s:string;
begin
s := "www.rambler.ru";
CreateThread(nil,SizeOf(s),@WBNavigate,pointer(s),0,c);
pointer(s):=nil; <-- 2
end;
← →
Leonid Troyanovsky © (2006-03-03 14:04) [9]
> GrayFace © (03.03.06 11:05) [8]
> Строки тоже можно передавать:
Не верю.
Т.е., не предложенным способом.
Кроме того, непонятно зачем <--2
--
Regards, LVT.
← →
begin...end © (2006-03-03 16:55) [10]> Leonid Troyanovsky © (03.03.06 14:04) [9]
> Т.е., не предложенным способом.
Можно и предложенным способом. Хотя и не нужно.
> Кроме того, непонятно зачем <--2
Да, в данном случае (присваивание константы-литерала) это лишнее.
← →
Leonid Troyanovsky © (2006-03-03 17:08) [11]
> begin...end © (03.03.06 16:55) [10]
> Можно и предложенным способом.
Зуб даешь? ;)
--
Regards, LVT.
← →
begin...end © (2006-03-03 17:13) [12]> Leonid Troyanovsky © (03.03.06 17:08) [11]
Зуб давать, конечно, не буду, но не вижу причин, по которым указанный способ в данном случае может быть нерабочим. Строка s при выходе из обработчика Button1Click не будет финализирована, и в поточную функцию передастся рабочий указатель на тело константной строки (плюс длину и счётчик ссылок, который -1). Почему бы этим указателем не воспользоваться внутри функции?
← →
Fay © (2006-03-03 17:46) [13]2 begin...end © (03.03.06 17:13) [12]
> при выходе из обработчика Button1Click
При выходе - это после выхода?
> не будет финализирована
А до какого момента?
← →
Fay © (2006-03-03 17:48) [14]Никто, кажется, не упомянул, что CreateThread - функция.
← →
begin...end © (2006-03-03 17:56) [15]> Fay © (03.03.06 17:46) [13]
> При выходе - это после выхода?
При выходе -- это в процессе выхода.
> А до какого момента?
В данном случае (в случае константной строки) -- до момента завершения процесса (причём даже если убрать последнюю строку обработчика из [8]). А в других случаях (например, когда счётчик ссылок у строки, объявленной в обработчике, будет равен 1, а не -1) -- до момента завершения функции потока, вероятно.
Тем не менее, просьба не считать меня приверженцем способов типа [8].
← →
Leonid Troyanovsky © (2006-03-03 18:07) [16]
> 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.
← →
Leonid Troyanovsky © (2006-03-03 18:11) [17]
> Fay © (03.03.06 17:48) [14]
> Никто, кажется, не упомянул, что CreateThread - функция.
Никто не говорил и про IsMultithread.
Но, в данном случае, не до утечки хендлов.
--
Regards, LVT.
← →
Fay © (2006-03-03 18:16) [18]2 Leonid Troyanovsky © (03.03.06 18:11) [17]
> Никто не говорил и про IsMultithread.
Дык IsMultithread может и не упоматься именно в этом участке кода.
← →
Leonid Troyanovsky © (2006-03-03 18:37) [19]
> Fay © (03.03.06 18:16) [18]
> Дык IsMultithread может и не упоматься именно в этом участке
> кода.
От чего же?
Для таких сочетаний как String & CreateThread оно вовсе не лишне.
--
Regards, LVT.
← →
Fay © (2006-03-03 18:40) [20]2 Leonid Troyanovsky © (03.03.06 18:37) [19]
> От чего же?
Да хоть в файле проекта
← →
begin...end © (2006-03-03 18:47) [21]> Leonid Troyanovsky © (03.03.06 18:07) [16]
> Потому, как некорректно.
Что некорректно? Пользоваться рабочим указателем?
> Рассмотрим следующий случай: ...
Этот пример не соответствует [8]. В [8] предотвращается финализация строки.
> Fay © (03.03.06 18:40) [20]
Уже неоднократно говорилось, что в Delphi следует использовать BeginThread вместо CreateThread. И дело не только в IsMultiThread.
← →
Leonid Troyanovsky © (2006-03-03 18:48) [22]
> Fay © (03.03.06 18:40) [20]
> > От чего же?
> Да хоть в файле проекта
Самый, IMHO, верный способ забыть о чем-то,
положить именно это туда.
Однако, замечание принято.
Хендлы надо закрывать всегда, а особенно - в учебных целях.
--
Regards, LVT.
← →
Fay © (2006-03-03 18:59) [23]2 begin...end © (03.03.06 18:47) [21]
> И дело не только в IsMultiThread.
А в чём ещё?
← →
begin...end © (2006-03-03 19:05) [24]> Fay © (03.03.06 18:59) [23]
В организации обработки исключений, например. См. код System.ThreadWrapper.
← →
Leonid Troyanovsky © (2006-03-03 19:11) [25]
> begin...end © (03.03.06 18:47) [21]
> Что некорректно? Пользоваться рабочим указателем?
..
> Этот пример не соответствует [8]. В [8] предотвращается
> финализация строки.
Ну, да. Рабочим его делает отложенная финализация,
сроки наступления которой еще требуют уточнений.
Для трех строчек кода неплохой результат, но для пятницы - тяжело.
Ладно, считай - зуб ты отстоял :)
--
Regards, LVT.
← →
Fay © (2006-03-03 19:14) [26]2 begin...end © (03.03.06 19:05) [24]
> См. код System.ThreadWrapper
Смотрел. Не понял 8(.
← →
GrayFace © (2006-03-04 15:01) [27]> Leonid Troyanovsky © (03.03.06 19:11) [25]
> Ну, да. Рабочим его делает отложенная финализация,
> сроки наступления которой еще требуют уточнений.
Финализация происходит в конце WBNavigate. В момент "<-- 1" в переменную s записывается переданная строка без увеличения счетчика ссылок (остается 1), а при завершении WBNavigate строка финализируется, т.к. на нее указывает переменная s.
← →
Leonid Troyanovsky © (2006-03-06 09:35) [28]
> GrayFace © (04.03.06 15:01) [27]
> Финализация происходит в конце WBNavigate. В момент "<--
> 1" в переменную s записывается переданная строка без увеличения
> счетчика ссылок (остается 1),
В переменную s просто записывается указатель (на раннее выделенную,
но неуничтоженную строку). Поэтому и не происходит никаких изменений
в ранее распределенном блоке, содержащем количество распределенных
байт, длину и счетчик ссылок, да и в самой строке).
Также понятно, как удается обмануть финализацию, бо наличие nil в
s интерпретируется как отсутствие у строки распределенного блока
размером 12+length.
Т.е., механизм этого стал понятен после [21] (зуб спасен ;)
Но, в общем-то, понятно, что этот способ ничем не лучше простого
GetMem с последующим освобождением в функции потока.
Бо, экономия пары строк кода ведет к полной его нечитаемости.
--
Regards, LVT.
← →
GrayFace © (2006-03-06 13:14) [29]Еще экономия времени на выделение и копирование памяти! =) А мне наоборот нравятся подобные хитрости.
Делал я ради интереса отложенную загрузку на Delphi - вот это вышло самое то - оптимально, компактно, красиво и абсолютно нечитаемо! Хотя, учитывая задачу, читаемость вышла вполне приемлемая.
← →
Leonid Troyanovsky © (2006-03-06 15:20) [30]
> GrayFace © (06.03.06 13:14) [29]
> Еще экономия времени на выделение и копирование памяти!
Нет никакой экономии. То, что оно делается неявно -
не означает, что выделения и освобождения нет.
--
Regards, LVT.
← →
GrayFace © (2006-03-06 15:35) [31]Резницы нет только если сразу с PChar"ом работать. А если вначале сделать строку, потом выделить память и переписать ее туда, то выделение и переписывание можно сэкономить.
← →
fobos © (2006-03-27 10:32) [32]Народ ... я хотел бы у Вас поитересоваться, ктонит знает как вызвать процедуру с неколькими параметрами к примеру MyProc(mems:TStringList;login:string;fp:conf;crypt:Word;path,ver:string); где fp - это тип используемый программой ... ?
← →
GrayFace © (2006-03-30 10:30) [33]Передавай адрес record"а, в котором все это содержится. Или включай их в наследника TThread.
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2006.07.02;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.012 c