我正在使用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 Windows7。为.NET 4.0中的x86构建的C#主机应用程序,为32位编译的Delphi DLL。
在多线程Delphi主机应用程序中使用时,该库似乎运行正常。
带有功能签名的DLL的MSVC版本extern __declspec(dllexport) void __stdcall Test(char testByte)
在C#主机上可以正常工作(这表明它特定于Delphi)。
如果库函数没有返回值(void
)和参数,则代码不会失败。
将两个代码中的调用约定更改为都cdecl
无济于事。
任何想法将不胜感激。
所有你需要做的是设置IsMultiThread
到True
(在你的DLL的主要一线begin
..end
块)的内存管理器切换到线程安全模式:
IsMultiThread := True;
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句