在多线程环境中从 C# 调用 Delphi DLL 时发生访问冲突
Access violation when calling Delphi DLL from C# in a multi-threaded environment
我正在使用 P/Invoke 从 C# 中调用用 Delphi XE2 编写的 DLL 函数。当从单个线程按顺序进行调用时,它似乎可以正常工作。但是,当多个线程调用该函数时,C# 主机应用程序看似随机抛出 System.AccessViolationException
。
为什么下面的代码会触发访问冲突,我该如何解决?
重现问题的最小 Delphi 库代码:
library pinvokeproblem;
{$R *.res}
uses Windows, SysUtils;
procedure Test(const testByte: byte); stdcall;
begin
OutputDebugString(PWideChar(IntToStr(testByte)));
end;
exports Test;
end.
重现问题的最低 C# 主机应用程序代码:
[DllImport(
"pinvokeproblem.dll",
CallingConvention = CallingConvention.StdCall,
EntryPoint = "Test")]
private static extern void Test(byte testByte);
public static void Main(string[] args)
{
for (int i = 1; i <= 1000; i++) // more iterations = better chance to fail
{
int threadCount = 10;
Parallel.For(1, threadCount, new ParallelOptions { MaxDegreeOfParallelism = threadCount }, test =>
{
byte byteArgument = 42;
Test(byteArgument);
Console.WriteLine(String.Format("Iteration {0}: {1}", test, byteArgument));
});
}
}
附加信息:
平台为 x64 Windows 7. C# 主机应用程序在 .NET 4.0 中为 x86 构建,Delphi DLL 为 32 位编译。
库在多线程 Delphi 主机应用程序中使用时似乎工作正常。
具有函数签名 extern __declspec(dllexport) void __stdcall Test(char testByte)
的 DLL 的 MSVC 版本在 C# 主机上运行良好(这表明这在某种程度上特定于 Delphi)。
如果库函数没有return值(void
)和参数,代码不会失败。
将两个代码中的调用约定更改为 cdecl
没有帮助。
如有任何想法,我们将不胜感激。
您所要做的就是将 IsMultiThread
设置为 True
(作为 DLL 主 begin
..end
块中的第一行)以切换内存线程安全模式管理器:
IsMultiThread := True;
我正在使用 P/Invoke 从 C# 中调用用 Delphi XE2 编写的 DLL 函数。当从单个线程按顺序进行调用时,它似乎可以正常工作。但是,当多个线程调用该函数时,C# 主机应用程序看似随机抛出 System.AccessViolationException
。
为什么下面的代码会触发访问冲突,我该如何解决?
重现问题的最小 Delphi 库代码:
library pinvokeproblem;
{$R *.res}
uses Windows, SysUtils;
procedure Test(const testByte: byte); stdcall;
begin
OutputDebugString(PWideChar(IntToStr(testByte)));
end;
exports Test;
end.
重现问题的最低 C# 主机应用程序代码:
[DllImport(
"pinvokeproblem.dll",
CallingConvention = CallingConvention.StdCall,
EntryPoint = "Test")]
private static extern void Test(byte testByte);
public static void Main(string[] args)
{
for (int i = 1; i <= 1000; i++) // more iterations = better chance to fail
{
int threadCount = 10;
Parallel.For(1, threadCount, new ParallelOptions { MaxDegreeOfParallelism = threadCount }, test =>
{
byte byteArgument = 42;
Test(byteArgument);
Console.WriteLine(String.Format("Iteration {0}: {1}", test, byteArgument));
});
}
}
附加信息:
平台为 x64 Windows 7. C# 主机应用程序在 .NET 4.0 中为 x86 构建,Delphi DLL 为 32 位编译。
库在多线程 Delphi 主机应用程序中使用时似乎工作正常。
具有函数签名
extern __declspec(dllexport) void __stdcall Test(char testByte)
的 DLL 的 MSVC 版本在 C# 主机上运行良好(这表明这在某种程度上特定于 Delphi)。如果库函数没有return值(
void
)和参数,代码不会失败。将两个代码中的调用约定更改为
cdecl
没有帮助。
如有任何想法,我们将不胜感激。
您所要做的就是将 IsMultiThread
设置为 True
(作为 DLL 主 begin
..end
块中的第一行)以切换内存线程安全模式管理器:
IsMultiThread := True;