[問題] 動態連結檔與Delegate、EventHandler問題

看板C_Sharp (C#)作者 (eva)時間6年前 (2019/02/26 23:26), 6年前編輯推噓5(5010)
留言15則, 4人參與, 6年前最新討論串1/1
各位先進大家好 最近在嘗試為量測儀器寫一個友善的介面 原先用加入參考的靜態方式把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

02/27 08:41, 6年前 , 1F
不好意思,問一下,什麼是靜態連結?
02/27 08:41, 1F

02/27 08:46, 6年前 , 2F
我覺得直接多一個按鈕,按下去就釋放已建立的外部元件就
02/27 08:46, 2F

02/27 08:46, 6年前 , 3F
好啦
02/27 08:46, 3F
就是直接在專案檔內加入DLL的參考(我是用VS) 就是對專案案右鍵->加入參考->選擇DLL檔案 這種在撰寫程式碼時就加入的DLL應該是靜態連結的方式吧?? (不好意思,專有名詞有點搞不太清楚) 因為是直接加入到參考內,要怎樣釋放我就不知道了....

02/27 10:07, 6年前 , 4F
動態連結的方式並部會解決你的問題,系統資源得自己釋
02/27 10:07, 4F

02/27 10:07, 6年前 , 5F
放。
02/27 10:07, 5F
可能是我說明不夠清楚,我用動態連結的方式有設定資源釋放 如果用上方的程式碼 有試過我設定按鈕按下,將objC0200=null; objC0=null; 然後要再次建立連線時,再重新建立新的物件, 但這樣就會回傳說USB PORT已使用的錯誤訊息 所以才會改用下方的方式, 設定按鈕按下後將物件=null 然後unload dll 這樣再次建立連線時,就不會有USB PORT已使用的問題 ※ 編輯: eva9234 (114.25.32.63), 02/27/2019 10:30:16

02/27 11:35, 6年前 , 6F
這跟靜態動態DLL連結沒關係吧。然後設成null不代表釋放資
02/27 11:35, 6F

02/27 11:36, 6年前 , 7F
源喔。通常都有個Dispose()可以呼叫才是主動釋放unmanaged
02/27 11:36, 7F
L大的意思是: objC0200.Dispose(); objC0200=null; 這樣吧? 但是objC0200.Dispose(); <-沒有Dispose(),所以會報找不到函式的錯誤 ※ 編輯: eva9234 (114.25.32.63), 02/27/2019 13:20:16

02/28 02:07, 6年前 , 8F
我覺得你的問題是出在 dll 沒有提供關閉連線的功能吧?如果
02/28 02:07, 8F

02/28 02:07, 6年前 , 9F
你是用把物件設成null的方式強制移出記憶體,那你試著在下
02/28 02:07, 9F

02/28 02:07, 6年前 , 10F
一行呼叫 GC ,看能不能提高穩定度
02/28 02:07, 10F

02/28 02:09, 6年前 , 11F
但最佳解還是用dll內的功能自行關閉連線,你要不要再翻翻
02/28 02:09, 11F

02/28 02:09, 6年前 , 12F
看文件?
02/28 02:09, 12F
是的,原廠的範例程式只是很簡單的連線→量測→關閉程式 所以沒有提供關閉連線的功能 但我需要的還有其他設定,所以才會想試其他方法釋放資源 呼叫CG有試過,但也是不成功...

02/28 12:16, 6年前 , 13F
樓上是釋放資源最佳解。但這邊還有個重要問題是,原po
02/28 12:16, 13F

02/28 12:16, 6年前 , 14F
的程式明明就是開啟中,且未釋放資源,是什麼原因造成斷
02/28 12:16, 14F

02/28 12:16, 6年前 , 15F
線問題呢,他創建的連線物件去哪裡了?
02/28 12:16, 15F
原本也沒想到要做中斷再連線的動作 起因是在開發中,無意中關掉了機器,但程式還是開啟的,所以就想直接再重新連線 就發現程式出錯中止 後來針對這問題做了詳細的測試,才發現只要程式連線過就會咬住 所以不管是使用者想中斷後再連線還是機器關掉再開、USB拔掉再插 不關閉整個程式就無法再次連接到機器 ※ 編輯: eva9234 (114.25.32.63), 02/28/2019 20:13:48
文章代碼(AID): #1STLgiLO (C_Sharp)
文章代碼(AID): #1STLgiLO (C_Sharp)