, 나는 COM 스레드 (TRemoteDataModule
) 내부 스레드를 만들었습니다. 이것은 내 구성 요소 공장입니다COM 스레드 내부에서 생성 된 스레드에서 CoInitialize를 호출 할 필요가없는 이유는 무엇입니까? 멀티 스레딩을 배우기 위해
: 스레드 내부
TComponentFactory.Create(ComServer, TServerConn2, Class_ServerConn2, ciMultiInstance, tmApartment);
는, 나는
.Exec
내가 읽고 ... TADOQuery.Create
, .Open
을 사용으로 CoInitialize를 호출하는 데 필요하지 않았다 I need to initialize the COM library on a thread before you call any of the library functions except CoGetMalloc, to get a pointer to the standard allocator, and the memory allocation functions.
그러나이 경우 CoInitialize가 없어도 아무런 문제가 발생하지 않았습니다.
는이 스레드 모델과 관련이 있습니까? 이 주제에 대한 설명은 어디에서 찾을 수 있습니까?
업데이트 : 내가 INSIDE 말할 때
, 그것은 COM 방법 컨텍스트 내에서 의미
interface
type
TWorker = class(TThread);
TServerConn2 = class(TRemoteDataModule, IServerConn2)
public
procedure Method(); safecall;
end;
implementation
procedure TServerConn2.Method();
var W: TWorker;
begin
W := TWorkerTread.Create(Self);
end;
업데이트 2 :
데이터베이스에 연결하는 데 사용되는 TADOConnection
은 현재 COM 스레드 컨텍스트 (TThread.Create constructor
)에서 만들어집니다. 비록 TADOConnection.Open
과 TADOQuery.Create/.Open
모두 TThread.Execute
내부에서 수행되고 있습니다.
UPDATE 3 - 시뮬
인터페이스 :
type
TServerConn2 = class;
TWorker = class(TThread)
private
FDB: TADOConnection;
FOwner: TServerConn2;
protected
procedure Execute; override;
public
constructor Create(Owner: TServerConn2);
destructor Destroy; override;
end;
TServerConn2 = class(TRemoteDataModule, IServerConn2)
ADOConnection1: TADOConnection;
procedure RemoteDataModuleCreate(Sender: TObject);
private
{ Private declarations }
protected
class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override;
procedure CheckException; safecall;
public
User, Pswd, Str: String;
Ok: Boolean;
end;
구현 :
class procedure TServerConn2.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string);
begin
if Register then
begin
inherited UpdateRegistry(Register, ClassID, ProgID);
EnableSocketTransport(ClassID);
EnableWebTransport(ClassID);
end else
begin
DisableSocketTransport(ClassID);
DisableWebTransport(ClassID);
inherited UpdateRegistry(Register, ClassID, ProgID);
end;
end;
{ TWorker }
constructor TWorker.Create(Owner: TServerConn2);
begin
inherited Create(False);
FreeOnTerminate := True;
FDB := TADOConnection.Create(nil);
FOwner := Owner;
end;
destructor TWorker.Destroy;
begin
FDB.Free;
FOwner.Ok := True;
inherited;
end;
procedure TWorker.Execute;
var Qry: TADOQuery;
begin
FDB.LoginPrompt := False;
FDB.ConnectionString := FOwner.Str;
FDB.Open(FOwner.User, FOwner.Pswd);
Qry := TADOQuery.Create(nil);
try
Qry.Connection := FDB;
Qry.LockType := ltReadOnly;
Qry.SQL.Text := 'SELECT TOP 1 * FROM MyTable';
Qry.Open;
finally
Qry.Free;
end;
end;
procedure TServerConn2.CheckException;
var W: TWorker;
begin
W := TWorker.Create(Self);
while not Ok do Sleep(100);
end;
procedure TServerConn2.RemoteDataModuleCreate(Sender: TObject);
begin
User := 'user';
Pswd := 'pass';
Str := ADOConnection1.ConnectionString;
end;
initialization
TComponentFactory.Create(ComServer, TServerConn2,
Class_ServerConn2, ciMultiInstance, tmApartment);
end.
UPDATE 4
오류는 여기에서 발생한다 : (? 때문에 TComponentFactory
의 아마)
function CreateADOObject(const ClassID: TGUID): IUnknown;
var
Status: HResult;
FPUControlWord: Word;
begin
asm
FNSTCW FPUControlWord
end;
Status := CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or
CLSCTX_LOCAL_SERVER, IUnknown, Result);
asm
FNCLEX
FLDCW FPUControlWord
end;
if (Status = REGDB_E_CLASSNOTREG) then
raise Exception.CreateRes(@SADOCreateError) else
OleCheck(Status);
end;
을 어떻게 든하여이 CoCreateInstance
는 TWorker
이 TServerConn2
보다 같은 컨텍스트에와 오류를 발생하지 않는 것이 확인?
스레드 프로 시저를 실행하기 전에? – Noseratio
모르겠다. Thread Model과 관련된 뭔가가 있다고 생각한다. – EProgrammerNotFound
.Net과 달리 @Noseratio는 델파이가 나에게'CoInitialize'를 호출하지 않는다! – EProgrammerNotFound