作者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://webptt.com/cn.aspx?n=bbs/C_Sharp/M.1551194796.A.558.html
※ 编辑: eva9234 (114.25.32.63), 02/26/2019 23:29:49
1F:推 s4300026: 不好意思,问一下,什麽是静态连结? 02/27 08:41
2F:推 s4300026: 我觉得直接多一个按钮,按下去就释放已建立的外部元件就 02/27 08:46
3F:→ s4300026: 好啦 02/27 08:46
就是直接在专案档内加入DLL的参考(我是用VS)
就是对专案案右键->加入参考->选择DLL档案
这种在撰写程式码时就加入的DLL应该是静态连结的方式吧??
(不好意思,专有名词有点搞不太清楚)
因为是直接加入到参考内,要怎样释放我就不知道了....
4F:→ cancelpc: 动态连结的方式并部会解决你的问题,系统资源得自己释 02/27 10:07
5F:→ 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
6F:推 Litfal: 这跟静态动态DLL连结没关系吧。然後设成null不代表释放资 02/27 11:35
7F:→ 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
8F:推 anumis: 我觉得你的问题是出在 dll 没有提供关闭连线的功能吧?如果 02/28 02:07
9F:→ anumis: 你是用把物件设成null的方式强制移出记忆体,那你试着在下 02/28 02:07
10F:→ anumis: 一行呼叫 GC ,看能不能提高稳定度 02/28 02:07
11F:→ anumis: 但最佳解还是用dll内的功能自行关闭连线,你要不要再翻翻 02/28 02:09
12F:→ anumis: 看文件? 02/28 02:09
是的,原厂的范例程式只是很简单的连线→量测→关闭程式
所以没有提供关闭连线的功能
但我需要的还有其他设定,所以才会想试其他方法释放资源
呼叫CG有试过,但也是不成功...
13F:推 s4300026: 楼上是释放资源最佳解。但这边还有个重要问题是,原po 02/28 12:16
14F:→ s4300026: 的程式明明就是开启中,且未释放资源,是什麽原因造成断 02/28 12:16
15F:→ s4300026: 线问题呢,他创建的连线物件去哪里了? 02/28 12:16
原本也没想到要做中断再连线的动作
起因是在开发中,无意中关掉了机器,但程式还是开启的,所以就想直接再重新连线
就发现程式出错中止
後来针对这问题做了详细的测试,才发现只要程式连线过就会咬住
所以不管是使用者想中断後再连线还是机器关掉再开、USB拔掉再插
不关闭整个程式就无法再次连接到机器
※ 编辑: eva9234 (114.25.32.63), 02/28/2019 20:13:48