I am calling a DLL function written in Delphi XE2 from C# using P/Invoke. It appears to be working when calls are made sequentially from a single thread. However, when multiple threads are calling the function, the C# host application throws System.AccessViolationException
seemingly at random.
Why does the code below trigger an access violation and how do I fix this?
Minimum Delphi library code for reproducing the problem:
library pinvokeproblem;
{$R *.res}
uses Windows, SysUtils;
procedure Test(const testByte: byte); stdcall;
begin
OutputDebugString(PWideChar(IntToStr(testByte)));
end;
exports Test;
end.
Minimum C# host application code to reproduce the problem:
[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));
});
}
}
Additional information:
Platform is x64 Windows 7. C# host application built for x86 in .NET 4.0, Delphi DLL compiled for 32-bit.
The library appears to be working OK when used in a multi-threaded Delphi host application.
An MSVC version of the DLL with the function signature
extern __declspec(dllexport) void __stdcall Test(char testByte)
works fine with the C# host (which suggests this is somehow specific to Delphi).The code will not fail if the library function has no return value (
void
) and arguments.Changing the calling convention in both code to
cdecl
did not help.
Any ideas would be much appreciated.
try..catch
block, I never managed to catch an exception. – Hydrocephalus