Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.02;
Скачать: CL | DM;

Вниз

Вызов процедуры в другом потоке с параметрами   Найти похожие ветки 

 
__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 вся ветка

Текущий архив: 2006.07.02;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.049 c
1-1148209778
vishnia
2006-05-21 15:09
2006.07.02
Разные стили шрифта в одном RichEdit


3-1146719497
TheEd
2006-05-04 09:11
2006.07.02
IB7: Unknown SQL Data type (590) при активации TIBTable!


15-1149223523
Ega23
2006-06-02 08:45
2006.07.02
С Днём рождения! 2 июня


10-1121666784
ORMADA
2005-07-18 10:06
2006.07.02
IDE получить имя текущего проекта


2-1149941024
demonygas
2006-06-10 16:03
2006.07.02
Плиз! Помогите осуществить перевод вешественного числа в строку