Currently, we use an unmanaged DLL from a vendor that allows us to access a particular instrument. The particular function of interest is specified in a header file as this:
extern "C" short CCONV acq_get_board_count ();
In my application, I have the pinvoke statement:
public class bograms
{
[DllImport("bograms.dll", EntryPoint = "acq_get_board_count", CallingConvention = CallingConvention.StdCall)]
public static extern short acq_get_board_count();
}
Now, in my code I am attempting to handle redundancy, so I create a timer that attempts to keep things running:
public class Instrument
{
private System.Threading.Timer keepAliveTimer;
public Instrument()
{
keepAliveTimer = new Timer(new TimerCallback(this.KeepAlive), null, 0, 300000);
}
void KeepAlive(object state)
{
if(instrumentIsUninitialized) // some check that accomplishes this
{
Console.WriteLine("Some status statements"); // in console
short numBoards = bograms.acq_get_board_count();
Console.WriteLine("Initialization caught {0} boards.", numBoards); // not in console
}
}
}
The first tick of the timer, it gets zero boards (presumably because the hardware is not finished initializing), and prints both messages to the console. However, the second tick, I get an APPCRASH error 0xc0000005 in the bograms.dll
, which I've found to be an Access Violation error. Putting try/catch around the call does not catch the error. The first line is in the console, the second line is not. When debugging the dump file (to the best of my limited knowhow), the error seems to occur on this call.
Is my pinvoke statement wrong? It's such a simple function that I can't believe it would be, but am I missing something? Is the threading due to the timer causing some type of problem?
I'm guessing the first call puts it into some type of state that results in the second call's failure, especially when considering the hardware initialization going on behind the scenes. If this is the case, is there any way to unload the driver DLL so it can reset back to the initial state it should be in?
Or are t开发者_开发技巧here any other things you can think of?
One thing that immediately comes to mind is whether the API can be used safely across threads. The System.Threading.Timer
callbacks come in on a ThreadPool
thread so it could be different each time. Some APIs have thread affinity requirements which means that they can only be called from a single thread. In lieu of that there still may be some concurrency problem if two calls to the same API occur simultaneously. In the end you may find out that the problem has nothing to do with threading. I am just trying to present one possible explanation.
精彩评论