多线程应用程序中的DLL和类 [英] DLL and class in multithreaded application

查看:92
本文介绍了多线程应用程序中的DLL和类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的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 ViolationInvalid 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.

这将解释AnsiStringWideString之间的行为差​​异,因为AnsiString是由Delphi内存管理器分配的,而WideString是在COM堆上分配的.当IsMultiThreadFalse时,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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆