2011-04-14 20 views
1

我放棄了,我不得不寫下來並提問;我正在使用Delphi編寫的非託管DLL,它在開發監視的硬件中發生事件時異步調用傳遞給它的(無參數)回調。從Delphi DLL回調到C# - 只適用於空閒的winform或使用app.doevents?

我在C#中做的事情是保持對創建委託的靜態引用,然後將其作爲參數傳遞給Delphi端的start方法。這告訴DLL使用回調通知我,每當有新數據要讀取時,使用GetData方法。

所有工作都很好,真的很好,直到我嘗試在控制檯應用程序或Windows服務中執行完全相同的操作。或者,如果我創建並在單獨的線程上調用DLL相關方法而不讓該線程執行Application.DoEvents()。通常情況下,有類似問題的人似乎在GC或調用約定方面存在問題,但通過讓代表參考文獻站在原位,沒有進一步的線索來解決GC問題。

我假設我在DLL調用連接到我的回調處理程序提供的thunk後CLR調用我的回調時丟失了一些至關重要的東西。

我的DLL進口的聲明看起來是這樣的:

[DllImport("TheDelphiApi.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] 
    private static extern UInt32 Start(MulticastDelegate callback); 

    [DllImport("TheDelphiApi.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] 
    private static extern void GetData(byte[] recdata); 

    public delegate void EngineCallbackHandler();      

    private static EngineCallbackHandler engineCallback; 

和呼叫建立回調:

 UInt32 result = Start(engineCallback); 

得到了線索?什麼是DoEvents的需要?任何反饋真的很感激,一直試圖研究這幾天,沒有任何跡象表明進展。 /J

+0

沒有提供給定代碼的線索。你說它需要一個winform來運行。也許代碼需要一個winform消息隊列在Delphi端運行? – CodingBarfield 2011-04-14 10:16:42

+0

不是根據德爾福開發人員,他使用它在服務(而不是沒有問題)。 – barbatron 2011-04-14 10:59:25

+0

德爾福服務具有主動消息泵。 – 2011-04-14 12:36:52

回答

1

很難說沒有看到本機代碼,但我會假設本機端的代碼取決於調用開始的線程上正在處理的消息循環?例如因爲它使用TTimer或類似的?

一旦對Start的調用返回,只有2種方法可以在DLL中執行任何代碼。一個新的線程被啓動,或者一個定時器或其他機制已經被註冊,這取決於窗口消息。

編輯:

另一種可能性:

如果本地DLL使用跨進程COM中的STA(單線程單元),然後COM取決於工作消息循環。

+0

我會調查是否有這樣的組件在Delphi DLL的某處使用。當然聽起來像一個似是而非的解釋。將Application.DoEvents放在服務的內部線程循環中可解決問題。我總體上覺得這不是一個很好的解決方法,但我猜它在這個時候是有效的。 – barbatron 2011-04-14 13:10:19

+0

那麼,如果某個庫需要一個工作消息循環,那麼它需要一個工作消息循環。這不是一個不常見的要求(例如,如果您與STA一起使用COM,也是如此)。但這是一個需要明確記錄的要求。 – 2011-04-14 23:13:24

+0

我明白了。沒有涉及到COM。我的回調從DLL中調用,作爲對來自UDP通信庫的中斷驅動回調的響應。所以據我瞭解,不應該依賴消息泵。但是我不得不承認,我對這一切「粘附」如何非常有限的理解。 – barbatron 2011-04-15 07:45:35