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

Вниз

CreateThread и метод класса   Найти похожие ветки 

 
Dust ©   (2005-07-12 12:03) [0]

CreateThread требует получить указатель на функцию и ни в каком виде не хочет принимать метод класса, а именно
procedure TClientSocket.DoLoop();
DoLoop - метод
-----
даже если написать так -
type ptoctype = Procedure();
var prctp : ptoctype;
то
никак не удастя сделать следующее присвоение -
prctp:=DoLoop;

А потому мне пришлось сделать функцию-обёртку, только для вызова одного метода.
Как вы поступали в таких ситуациях? Существует ли другой выход?


 
имя   (2005-07-12 12:07) [1]

Удалено модератором


 
Юрий Зотов ©   (2005-07-12 13:01) [2]

> CreateThread требует получить указатель на функцию и ни в
> каком виде не хочет принимать метод класса

Что и естественно. Методы классов имеют еще один (неявный) параметр (Self) - и, таким образом, получается несовпадение числа параметров.

> Существует ли другой выход?

CreateThread, среди прочих параметров, принимает указатель на данные пользователя, а затем передает его функции потока. Если через этот указатель передать экземпляр объекта, то функция потока сможет его использовать - в том числе, вызывать его методы.

Только тут надо быть аккуратным - вызывать метод объекта из другого потока можно лишь если этот метод потокобезопасен.


 
Alex Konshin ©   (2005-07-12 13:03) [3]

Кстати, используй BeginThread вместо CreateThread.


 
begin...end ©   (2005-07-12 13:04) [4]

> Dust ©   (12.07.05 12:03)

Если параметров нет (и внутри метода не используется Self -- явно или неявно), то всё просто.

type
 TMyForm = class(TForm)
   ...
 private
   procedure M;
 end;

var
 Id, H: Cardinal;

procedure TMyForm.Button1Click(Sender: TObject);
type
 TObjProc = procedure of object;
 TProc = procedure;
var
 OP: TObjProc;
 P: TProc;
begin
 OP := M;
 P := TMethod(OP).Code;
 H := CreateThread(nil, 0, @P, nil, 0, Id);
 Win32Check(H <> 0)
end;

procedure TMyForm.M;
begin
 Application.MessageBox("Ура, товарищи!", "Ура!")
end.


P.S. CreateThread выкинуть. Использовать BeginThread.


 
Digitman ©   (2005-07-12 13:05) [5]


> Dust ©   (12.07.05 12:03)


> требует получить указатель на функцию


если требует именно функцию, какого ж лешего ты пытаешься не функцию, а процедуру (неважно - регулярную или метод класса) "подсунуть" ?


 
isasa ©   (2005-07-12 13:13) [6]

Не принципиально

BeginThread(...)
=
IsMultiThread := TRUE;
CreateThread(...);


 
Alex Konshin ©   (2005-07-12 13:13) [7]

Там не только это.


 
Dust ©   (2005-07-12 13:22) [8]

TO: begin...end, Alex Konshin
ясно, спасибо,,,, но чем лучше BeginThread нежели CreateThread??


 
Dust ©   (2005-07-12 13:24) [9]

какая разница, будет ли этот флаг стоять...


 
begin...end ©   (2005-07-12 13:24) [10]

> Dust ©   (12.07.05 13:22) [8]

См. справку по BeginThread.


 
isasa ©   (2005-07-12 13:42) [11]

>Там не только это.

модуль System

function BeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
 ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
 var ThreadId: LongWord): Integer;
var
 P: PThreadRec;
begin
 New(P);
 P.Func := ThreadFunc;
 P.Parameter := Parameter;
 IsMultiThread := TRUE;
 Result := CreateThread(SecurityAttributes, StackSize, @ThreadWrapper, P,
   CreationFlags, ThreadID);
end;


 
Alex Konshin ©   (2005-07-12 13:42) [12]

Флаг этот важный. Он говорит менеджеру памяти, что нужно использовать синхронизацию.
Помимо этого там инициируется что-то в TLS и, насколько я помню, формируется фрейм на стеке. Иначе будут проблемы при exception.


 
Alex Konshin ©   (2005-07-12 13:44) [13]

isasa ©   (12.07.05 13:42) [11]
Ну и посмотри внимательнее на параметры CreateThread


 
isasa ©   (2005-07-12 13:48) [14]

Кроме
IsMultiThread := TRUE;
все транзит.
Я работаю с  CreateThread и не имею головной боли, что такое ThreadWrapper и где его искать.


 
Alex Konshin ©   (2005-07-12 13:56) [15]

ThreadWrapper там же.
Borland предупредил, а ты волен поступать как хочешь. Только предупреди пож-ста, какие программы ты написал, чтоб случайно не купить.
Кстати, в VC тоже существует обертка для этой API функции (по-моему даже называется так же) по той же причине.


 
isasa ©   (2005-07-12 14:08) [16]

Работает начиная с D4(не сам придумал - Калверт посоветовал :))
Это просто прокладка ( :) ) для обеспечения кросс-платформы,
кроме того

function ThreadWrapper(Parameter: Pointer): Integer; stdcall;

формально, является

function ThreadWrapper(Parameter: PThreadRec): Integer; stdcall;

вот и помни. Неудобно.


 
Alex Konshin ©   (2005-07-12 14:18) [17]

А зачем тебе это помнить? Есть BeginThread, вот и используй.
Сама-то функция CreateThread конечно работает, но она не делает инициализацию нити для использования с RTL Delphi. Как я уже сказал, абсолютно аналогичная ситуация и для других RTL, например, для VC.
И там вовсе не обеспечение кроссплатформенности. Да, там есть понимание платформы, но именно для выполнения требуемых действий на той платформе, а эта функция была и в D3, где linux и не пахло. Там инициализируется FPU и стек. Потенциально неиспользование BeginThread может привести к неверной обработке исключений в нити. Выглядит это так, что при исключении нить просто пропадает, даже чирикнуть не успевает.
Наверно и какие-то эффекты с FPU, но я практически никогда FPU не использую, так что не в курсе, чем это грозит.


 
isasa ©   (2005-07-12 14:34) [18]

Про FPU (floationg point unit - сопроцессор плавающей арифметики) - не понял.
Чего его инициализировать. Он или есть, или его нет.
Соответсвенно код компилируется или с инструкциями для него, или с эмуляцией оных.


 
Alexander Panov ©   (2005-07-12 15:19) [19]

isasa ©   (12.07.05 13:48) [14]
Я работаю с  CreateThread и не имею головной боли,


А почему ты должен ее иметь?

Вот только BeginThread простейшая надстройка и ей пользоваться удобнее тем, что не надо думать о том, что для CreateThread, например, соглашение о передаче параметров StdCall...


 
evvcom ©   (2005-07-12 16:32) [20]


> Про FPU (floationg point unit - сопроцессор плавающей арифметики)
> - не понял.
> Чего его инициализировать. Он или есть, или его нет.

Я нарывался на ошибки сопроцессора в казалось бы безобидных ситуациях типа y := round(x); и получал через раз ошибку деления на ноль. Начал выяснять, оказалось неверно инициализировались служебные регистры FPU. А ты говоришь, чего инициализировать!


 
isasa ©   (2005-07-12 17:18) [21]

А если у меня процессор P4 с гипертрайдингом, где FPU фактически второй процессор, то инициализация его регистров
внутри приложения (процесса) выглядит по меньшей мере странно.


 
ANB ©   (2005-07-12 17:24) [22]


> если требует именно функцию,
- а какя разница (с точки зрения Windows) между процедурой и функцией ?


 
DiamondShark ©   (2005-07-12 18:25) [23]

Кого-то очень сильно клинит...


 
Alex Konshin ©   (2005-07-12 23:22) [24]

isasa ©   (12.07.05 17:18) [21]
А если у меня процессор P4 с гипертрайдингом, где FPU фактически второй процессор, то инициализация его регистров
внутри приложения (процесса) выглядит по меньшей мере странно.

При переключении нитей состояние всех регистров сохраняются-восстанавливаются. Так что как инициализировал, так и будет. HT тут абсолютно ни при чем. Кстати, и для процесса могут сохраняться некие установки, по крайней мере я видел это в исходниках Windows CE, не думаю, что в NT+ сильно иначе.



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

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

Наверх




Память: 0.53 MB
Время: 0.047 c
3-1119472246
серго
2005-06-23 00:30
2005.07.31
не получается работать с компонентом DBMemo


1-1121361600
Igor_thief
2005-07-14 21:20
2005.07.31
Что за компонент?


8-1112082622
ut1wpr
2005-03-29 11:50
2005.07.31
Генерация двух тонов одновременно. Консольное приложение.


6-1114148067
marcel
2005-04-22 09:34
2005.07.31
Автоматическое обновление компонентов ПО


1-1121065795
Курдль
2005-07-11 11:09
2005.07.31
Про отображение BLOB типа jpeg в DBImage