PeterK
PeterK

Reputation: 3817

Access violation when calling Delphi DLL from C# in a multi-threaded environment

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:

Any ideas would be much appreciated.

Upvotes: 8

Views: 1375

Answers (1)

Ondrej Kelle
Ondrej Kelle

Reputation: 37211

All you have to do is set IsMultiThread to True (as the first line in your DLL's main begin..end block) to switch the memory manager to a thread-safe mode:

IsMultiThread := True;

Upvotes: 11

Related Questions