0

I access a c++ dll library from c# code in a WPF application. I have no problems while accessing the dll from the ui thread. But I need the UI to be responsive while the code of the c++ dll is running. So I try to access it from another thread. But when I try to call the same function (that I call from the ui thread) in a non-ui thread for the first time, the function returns but the return value indicates there is an internal error in the function. But when I run the code from a non-ui thread once or twice more, it successfully returns a non-error value. I don't have the source code of the dll so I am not sure what happens inside.

c++ function

UINT32 myfunc1()

In C#

[DllImport("mydll.dll")]
public static extern uint myfunc1();

How I reach the code in ui thread

uint errorCode = myfunc1(); // returns 0 means no error occured

How I reach the code in non-ui thread

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, args) => { args.Result = myfunc1(); };
// 1st call args.Result is 10 means internal error ocurred
// 2nd call args.Result is sometimes 0 and sometimes 10
// 3rd or later calls args.Result is 0 means no error occured
worker.RunWorkerCompleted += doSth();
worker.RunWorkerAsync();
fonurr
  • 75
  • 2
  • 8

1 Answers1

1

It "might" have something to do with the Apartment model being used on threads.

Your UI thread will be using the STA (Single Threaded Apartment) model...it relies on the message loop for synchronization/serializing access.

Your BackgroundWorker will be using the MTA (Multi-Threaded Apartment) model.

There's probably some code in that DLL library that relies on being run in a UI/STA thread for proper synchronization e.g. some COM calls perhaps. The reason it sometimes works, and sometimes doesn't is probably down to a race condition...due to lack of synchronization.

It's possible to specify that a thread is an STA one....but not on BackgroundWorker threads, because they are created and managed by a ThreadPool and are always set to use the MTA apartment model, get reused, etc....and a Thread must have it's apartment state set before it is started...after which it cannot be changed.

So instead create a new Thread set its apartment to STA, and also pump a messageloop.

Community
  • 1
  • 1
Colin Smith
  • 12,375
  • 4
  • 39
  • 47