作者eva9234 (eva)
看板C_Sharp
標題[問題] 動態連結檔與Delegate、EventHandler問題
時間Tue Feb 26 23:26:34 2019
各位先進大家好
最近在嘗試為量測儀器寫一個友善的介面
原先用加入參考的靜態方式把DLL讀進來後
可以很順利地執行運作
但碰到一個問題
就是連線成功後
DLL就會咬住儀器的USB PORT不放
導致如果突然中斷連線後
程式就無法再連上儀器
一定要關閉程式再開才有辦法在連上
所以想將原先靜態連結DLL的方式全都改成用動態連結
但是有一行有關Delegate、EventHandler的部分可能我觀念太差
一直改不成功
希望有先進能指導我一下
靜態連結程式碼:
public partial class Form1 : Form
{
//宣告
private InteropSRVRLib.C0200 objC0200;
private InteropSRVRLib.C0 objC0;
private void button1_Click(object sender, EventArgs e)
{
objC0200 = new InteropSRVRLib.C0200();
objC0 = objC0200.SingleC0;
//就是這一行
objC0.ExeCal += new InteropSRVRLib._C0Events_ExeCalEventHandler(
objC0_ExeCal);
....
}
private void objC0_ExeCal()
{
....
}
}
動態連結程式碼:
public partial class Form1 : Form
{
//宣告
private dynamic InteropSRVRLib_C0200;
//objC0200;
private dynamic InteropSRVRLib_C0;
//objC0;
private void button2_Click(object sender, EventArgs e)
{
Assembly assembly = Assembly.LoadFile("InteropSRVRLib.dll");
Type type1 = assembly.GetType("InteropSRVRLib.C0200Class");
//對應objC0200 = new InteropSRVRLib.C0200();
InteropSRVRLib_C0200 = Activator.CreateInstance(type1);
//對應objC0 = objC0200.SingleC0;
InteropSRVRLib_C0 = InteropSRVRLib_C0200.SingleC0;
//以下一大段都只為了實現objC0.ExeCal +=
// new InteropSRVRLib._C0Events_ExeCalEventHandler(objC0_ExeCal);
Type type2 = assembly.GetType("InteropSRVRLib.C0Class");
EventInfo ev1 = type2.GetEvent("ExeCal");
MethodInfo objC0_ExeCalMethod = typeof(Form1).GetMethod("objC0_ExeCal",
BindingFlags.NonPublic | BindingFlags.Instance);
//Type type3 = assembly.GetType("InteropSRVRLib._C0Events_ExeCalEventHandler");
//dynamic c = Activator.CreateInstance(type3,objC0_ExeCalMethod);
//↑也是錯誤,說不到建構子
Delegate d = Delegate.CreateDelegate(ev1.EventHandlerType,
objC0_ExeCalMethod);
//↑想要製造 d = InteropSRVRLib._C0Events_ExeCalEventHandler(objC0_ExeCal)
// 但執行後卻一直報錯說"繫結至目標方法時發生錯誤。"
ev1.AddEventHandler(InteropSRVRLib_C0.ExeCal, d);
//應該是對應objC0.ExeCal += d的意思吧?
.....
}
private void objC0_ExeCal()
{
....
}
}
Delegate.CreateDelegate應該怎麼改連結的到目標啊??
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.25.32.63
※ 文章網址: https://www.ptt.cc/bbs/C_Sharp/M.1551194796.A.558.html
※ 編輯: eva9234 (114.25.32.63), 02/26/2019 23:29:49
推 s4300026: 不好意思,問一下,什麼是靜態連結? 02/27 08:41
推 s4300026: 我覺得直接多一個按鈕,按下去就釋放已建立的外部元件就 02/27 08:46
→ s4300026: 好啦 02/27 08:46
就是直接在專案檔內加入DLL的參考(我是用VS)
就是對專案案右鍵->加入參考->選擇DLL檔案
這種在撰寫程式碼時就加入的DLL應該是靜態連結的方式吧??
(不好意思,專有名詞有點搞不太清楚)
因為是直接加入到參考內,要怎樣釋放我就不知道了....
→ cancelpc: 動態連結的方式並部會解決你的問題,系統資源得自己釋 02/27 10:07
→ cancelpc: 放。 02/27 10:07
可能是我說明不夠清楚,我用動態連結的方式有設定資源釋放
如果用上方的程式碼
有試過我設定按鈕按下,將objC0200=null; objC0=null;
然後要再次建立連線時,再重新建立新的物件,
但這樣就會回傳說USB PORT已使用的錯誤訊息
所以才會改用下方的方式, 設定按鈕按下後將物件=null
然後unload dll
這樣再次建立連線時,就不會有USB PORT已使用的問題
※ 編輯: eva9234 (114.25.32.63), 02/27/2019 10:30:16
推 Litfal: 這跟靜態動態DLL連結沒關係吧。然後設成null不代表釋放資 02/27 11:35
→ Litfal: 源喔。通常都有個Dispose()可以呼叫才是主動釋放unmanaged 02/27 11:36
L大的意思是:
objC0200.Dispose();
objC0200=null;
這樣吧?
但是objC0200.Dispose(); <-沒有Dispose(),所以會報找不到函式的錯誤
※ 編輯: eva9234 (114.25.32.63), 02/27/2019 13:20:16
推 anumis: 我覺得你的問題是出在 dll 沒有提供關閉連線的功能吧?如果 02/28 02:07
→ anumis: 你是用把物件設成null的方式強制移出記憶體,那你試著在下 02/28 02:07
→ anumis: 一行呼叫 GC ,看能不能提高穩定度 02/28 02:07
→ anumis: 但最佳解還是用dll內的功能自行關閉連線,你要不要再翻翻 02/28 02:09
→ anumis: 看文件? 02/28 02:09
是的,原廠的範例程式只是很簡單的連線→量測→關閉程式
所以沒有提供關閉連線的功能
但我需要的還有其他設定,所以才會想試其他方法釋放資源
呼叫CG有試過,但也是不成功...
推 s4300026: 樓上是釋放資源最佳解。但這邊還有個重要問題是,原po 02/28 12:16
→ s4300026: 的程式明明就是開啟中,且未釋放資源,是什麼原因造成斷 02/28 12:16
→ s4300026: 線問題呢,他創建的連線物件去哪裡了? 02/28 12:16
原本也沒想到要做中斷再連線的動作
起因是在開發中,無意中關掉了機器,但程式還是開啟的,所以就想直接再重新連線
就發現程式出錯中止
後來針對這問題做了詳細的測試,才發現只要程式連線過就會咬住
所以不管是使用者想中斷後再連線還是機器關掉再開、USB拔掉再插
不關閉整個程式就無法再次連接到機器
※ 編輯: eva9234 (114.25.32.63), 02/28/2019 20:13:48