非托管 DLL 的访问冲突
目前,我们使用供应商提供的非托管 DLL,它允许我们访问特定的仪器。感兴趣的特定函数在头文件中指定如下:
extern "C" short CCONV acq_get_board_count ();
程序中,我有 pinvoke 语句:
public class bograms
{
[DllImport("bograms.dll", EntryPoint = "acq_get_board_count", CallingConvention = CallingConvention.StdCall)]
public static extern short acq_get_board_count();
}
现在,在我的代码中,我尝试处理冗余,因此我创建一个尝试保持运行的计时器:
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
}
}
}
在我的应用 计时器的滴答声,它得到零个板(大概是因为硬件尚未完成初始化),并将两条消息打印到控制台。但是,在第二次勾选时,我在 bograms.dll
中收到 APPCRASH 错误 0xc0000005,我发现这是一个访问冲突错误。在调用周围放置 try/catch 不会捕获错误。第一行在控制台中,第二行不在控制台中。调试转储文件时(尽我有限的专业知识),错误似乎发生在这次调用上。
我的pinvoke声明有错吗?这是一个如此简单的功能,我简直不敢相信它会是这样,但我是否遗漏了一些东西?计时器引起的线程是否会导致某种类型的问题?
我猜测第一个调用将其置于某种类型的状态,导致第二个调用失败,特别是在考虑幕后进行的硬件初始化时。如果是这种情况,是否有任何方法可以卸载驱动程序 DLL,以便它可以重置回应有的初始状态?
或者你还能想到其他什么吗?
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 there any other things you can think of?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
立即想到的一件事是 API 是否可以跨线程安全地使用。 System.Threading.Timer 回调位于 ThreadPool 线程中,因此每次都可能不同。某些 API 具有线程亲和性要求,这意味着它们只能从单个线程调用。相反,如果同时发生对同一 API 的两次调用,仍然可能会出现一些并发问题。最后你可能会发现问题与线程无关。我只是想提出一种可能的解释。
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 aThreadPool
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.