Доброго дня господа !
Имею первичную постановку
1.Динамический вызов из библиотека DLL
2.Создаю пользовательский объект AddSpan
3.Основная функция объекта AddSpan это Execute
4.Поле объекта Thread, который может запуска Execute в потоке (по потребности)
5.Возврат значения RecordSet, по результатам выполнения (в примере возвращаю String)
Проблема при вызове в потоке, невозможно вернуть результат
Возможное решение
1. При создание AddSpan - фиксирую адрес ячейки
constructor TAddSpan.Create(aFile: String; aBars: TProgressBar; Terminate: TTerminate; var aSql: OleVariant);
...............
pSql:=@aSql;
................
2.При создании поля-потока, фикcирую родитель-объект
constructor TAddExec.Create(aHandleParent: TAddSpan; aExecute: TExecute; aTerminate: TTerminate);
................
HandleParent :=aHandleParent;
................
3.При окончании работы потока - уничтожаю родитель-объект, предварительно по адресу
передав результат выполнения функции Execute
procedure TAddExec.TerminateThread(Sender: TObject);
begin
HandleParent.pSql^:=OleVariant(HandleParent.SQL); - возврат результата
HandleParent.Free;
HandleParent:=Nil;
AddTerminate(Sender); - доп. процедура которая в основной форме
end;
Не нравится
- " окончания работы потока - уничтожаю родитель-объект"
уничтожить из дочери - родителя - не есть архитектурно !
- слишком сексуально !!!! и много извращений связанных с адресами переменных
Но другого решения увы не нашел.
О великие ГУРУ прошу подсказать более технологичное решение (можно с примером)
Заранее благодарен !
Имею код вызова
Create_AddSpan: function(aFile: String; aList: String; aThread: Boolean; aBar: TProgressBar; Terminate: TTerminate; var aSql: OleVariant): Integer; stdcall;
@Create_AddSpan:=nil;
LibHandle := LoadLibrary('MyLibrary.dll');
if LibHandle >= 32 then begin
@Create_AddSpan:=GetProcAddress(LibHandle,'Create_AddSpan');
if @Create_AddSpan<>nil then Create_AddSpan(aFile,aList,True,pbMain,TerminateThread,ovSql);
end;
FreeLibrary(LibHandle); //если поток уничтожать нельзя
Пользовательский класс
unit AddSpan;
type
POleVariant = ^OleVariant;
TAddSpan = class;
TExecute = procedure of object;
TTerminate = procedure(Sender: TObject) of object;
TAddExec = class(TThread)
private
ParentExecute: TExecute;
AddTerminate: TTerminate;
protected
//
public
HandleParent: TAddSpan;
constructor Create(aHandleParent: TAddSpan; aExecute: TExecute; aTerminate: TTerminate);
procedure Execute; override;
procedure TerminateThread(Sender: TObject);
published
//
end;
TAddSpan = class(TObject)
private
thExec: TAddExec;
mtExit: TTerminate;
pSql: POleVariant;
protected
//
public
SQL: String;
constructor Create(aFile: String; aBars: TProgressBar; Terminate: TTerminate; var aSql: OleVariant); virtual;
procedure Execute;
procedure ExecuteThread;
published
//
end;
implementation
function Create_AddSpan(aFile: String; aList: String; aThread: Boolean; aBar: TProgressBar; Terminate: TTerminate; var aSql: OleVariant): Integer;
var A: TAddSpan;
I: Integer;
L: Boolean;
S,List: String;
begin
A:=TAddSpan.Create(aFile,aBar,Terminate,aSql);
.........................
if aThread then A.ExecuteThread else A.Execute;
//если поток уничтожать нельзя - 3-и строки это ошибка
aSql:=OleVariant(A.sSql);
A.Free;
A:=Nil;
end;
constructor TAddExec.Create(aHandleParent: TAddSpan; aExecute: TExecute; aTerminate: TTerminate);
begin
Inherited Create(True);
HandleParent :=aHandleParent;
ParentExecute :=aExecute;
AddTerminate :=aTerminate;
FreeOnTerminate:=True;
OnTerminate :=TerminateThread;
end;
procedure TAddExec.TerminateThread(Sender: TObject);
begin
HandleParent.pSql^:=OleVariant(HandleParent.SQL);
HandleParent.Free;
HandleParent:=Nil;
AddTerminate(Sender);
end;
procedure TAddExec.Execute;
begin
ParentExecute;
end;
constructor TAddSpan.Create(aFile: String; aBars: TProgressBar; Terminate: TTerminate; var aSql: OleVariant);
var I: Integer;
S: TArrayStr;
Sect,Note: String;
begin
Inherited Create;
.........................
mtExit:=Terminate;
pSql:=@aSql;
end;
destructor TAddSpan.Destroy;
begin
.................
inherited;
end;
procedure TAddSpan.Execute;
var I: Integer;
L: Boolean;
begin
CoInitialize(nil);
try
SQL:='значение этой переменной нужно вернуть';
................................
end;
CoUninitialize;
end;
procedure TAddSpan.ExecuteThread;
begin
thExec:=TAddExec.Create(Self,Self.Execute,Self.mtExit);
thExec.Resume;
end;
end.