多线程应用程序中的DLL和类 [英] DLL and class in multithreaded application
问题描述
我的DLL中有一个类.并且该DLL提供了一个接口"来创建此类的对象并调用其方法.
I have a class inside my DLL. And this DLL provides an "interface" to create objects of this class and call their methods.
类代码(简体):
TLogger = class
private
//
public
function AddToLog(sBuf: PWideChar): Word;
constructor Create(Name: PWideChar);
destructor Destroy; override;
end;
constructor Create(Name: PWideChar);
begin
//
end;
destructor TLogger.Destroy;
begin
//
end;
function TLogger.AddToLog(sBuf: PWideChar): Word;
var
Temp1 : WideString;
Temp2 : AnsiString;
begin
Result := NO_ERRORS;
WaitForSingleObject( FMutex, INFINITE );
Temp1 := 'a';
Temp2 := Temp1;
//
ReleaseMutex( FMutex );
end;
DLL代码
function CreateLogger( LogFileName: PWideChar; PLogger: PCardinal): Word; stdcall;
begin
try
PLogger^ := Cardinal(TLogger.Create(LogFileName));
Result := NO_ERRORS;
except
Result := ERR_CREATE_OBJECT;
end;
end;
function DestroyLogger( PLogger: Cardinal ): Word; stdcall;
begin
try
TLogger(PLogger).Free;
Result := NO_ERRORS;
except
Result := ERR_OBJECT_NOT_FOUND;
end;
end;
function AddToLog( PLogger: Cardinal; BufStr: PWideChar ): Word; stdcall;
begin
try
Result := TLogger(PLogger).AddToLog( BufStr );
except
Result := ERR_OBJECT_NOT_FOUND;
end;
end;
当我尝试从1个线程使用此库时,一切正常.当我创建许多随机调用函数AddToLog
的线程时,问题就开始了(每个线程都有它自己的类的对象).有时我会碰到Access Violation
或Invalid pointer operation
.
我进行了一些研究,并指出,如果变量Temp2
具有WideString
类型,则一切正常.另一个解决方案是将互斥锁移到库代码(这只是一个研究"代码):
When I'm trying to use this library from 1 thread - everything is OK. The problems start when I create many threads that call function AddToLog
with random periods (each thread has it's own object of the class). In some time I catch Access Violation
or Invalid pointer operation
.
I've made some research and pointed out that if variable Temp2
has WideString
type everything is OK. Another solution is to move mutex to the library code (it's just a "research" code):
function AddToLog( PLogger: Cardinal; BufStr: PWideChar ): Word; stdcall;
begin
WaitForSingleObject( TLogger(PLogger).FMutex, INFINITE );
Result := TLogger(PLogger).AddToLog( BufStr );
ReleaseMutex( TLogger(PLogger).FMutex );
end;
第二种解决方案对我不利,因为每个对象都有它自己的互斥体(想法是,如果两个对象必须使用一个文件,则它们具有相同的互斥体来等待;如果两个对象必须使用不同的文件,则它们有不同的互斥锁,并且可以并行工作.)
The second solution is bad for me because each object has it's own mutex (idea is that if two objects must work with one file, they have the same mutex to wait each other; if two objects must work with different files, they have different mutexes and work in parallel).
我试图解决此问题已有2天,但我不知道出了什么问题.字符串转换如何导致此类问题?
I'm trying to solve this problem for 2 days but I can't understand what goes wrong. How string cast can cause such problem?
推荐答案
放入以下行:
IsMultiThread := True;
作为DLL项目的主要代码块的第一行.这将指示内存管理器切换到线程安全模式.
as the first line in your DLL project's main code block. This will instruct the memory manager to switch to a thread-safe mode.
这将解释AnsiString
和WideString
之间的行为差异,因为AnsiString
是由Delphi内存管理器分配的,而WideString
是在COM堆上分配的.当IsMultiThread
为False
时,Delphi内存管理器不是线程安全的,但是COM堆始终是线程安全的.
This would explain a behaviour difference between AnsiString
and WideString
because AnsiString
is allocated by the Delphi memory manager, and WideString
is allocated on the COM heap. When IsMultiThread
is False
, the Delphi memory manager is not thread-safe, but the COM heap is always thread-safe.
这篇关于多线程应用程序中的DLL和类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!