Текущий архив: 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.51 MB
Время: 0.206 c