目前,我們使用供應商提供的非託管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
}
}
}
定時器的第一跳,它得到零塊板(大概是因爲硬件沒有完成初始化),一個d將這兩個消息打印到控制檯。但是,第二次打勾,我得到了bograms.dll
中的APPCRASH錯誤0xc0000005,這是我發現的訪問衝突錯誤。將try/catch放在調用中並不會發現錯誤。第一行在控制檯中,第二行不在。在調試轉儲文件時(盡我所知有限),錯誤似乎發生在這次調用中。
我的口供錯誤是否錯誤?這是一個簡單的功能,我不敢相信它,但我錯過了什麼?計時器引起的線程是否會導致某些類型的問題?
我猜測第一次調用會將它置於某種導致第二次調用失敗的狀態,特別是當考慮在後臺進行硬件初始化時。如果是這種情況,有沒有辦法卸載驅動程序DLL,以便它可以重置回它應該在的初始狀態?
或者還有什麼其他的事情可以想到嗎?
我知道這已經有一段時間了,但是我在過去一個月裏一直在測試這個理論,而且我認爲你對線程相關性的理解是正確的,特別是因爲我使用Timer來完成KeepAlive任務。儀器的驅動程序必須在第一次調用時存儲一些信息,而在第二次調用時(它發生在另一個線程上),它會嘗試訪問該位內存,並因違規而失敗。但是,我不知道如何解決這個問題...我是否使用'Thread.Sleep()'將每個KeepAlive的延時更改爲單循環?我聽說過關於睡覺的壞事... – drharris 2010-10-01 22:21:14
你有沒有得到任何與此?我有完全相同的問題。 – Brandon 2014-07-23 14:30:01