Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
2-1149830550
graf
2006-06-09 09:22
2006.07.02
И снова вопрос о FTP


2-1149710958
Fiallo4ka
2006-06-08 00:09
2006.07.02
запросы


1-1148406755
Juice
2006-05-23 21:52
2006.07.02
Вывести в меню список окон моего приложения


4-1143575019
Noby
2006-03-28 23:43
2006.07.02
Кнопки мыши


15-1149585343
Ribachok
2006-06-06 13:15
2006.07.02
Создание отчёта





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