没有用过C#,但是在使用别人编写的C#程序,发现问题,请别人来解决了一下,这里只是把别人解决的方法放在这里,备查。
要解决的问题是这样的,C#写界面,底层调用C++写的动态库提供的函数。界面上有个按钮,一点按钮弹出窗口,在窗口中可以查询远端的数据并显示在这个弹出窗口中。查询远端的数据调用的就是C++动态库提供的函数,函数中有个参数是回调函数。这个回调函数的作用是底层从远端获得数据后,通过回调函数通知C#数据是什么,由C#界面(就是这个弹出窗口)显示出来。
这是在C#中对C++动态库接口函数的定义:
public static extern bool QueryRecords(ref XQuery xQuery,
ref RecordQuery recordQuery,
FuncQueryRecords callbackFuncQuery);
原来的代码,在点击弹出窗口的查询按钮后,这样调用:
bool abc = ServerControl.QueryRecords(ref x, ref query, RecordInfo);
其中,RecordInfo是个在C#中定义的函数,用于接收数据后显示数据:
在这个函数之前,先有个委托的定义
private delegate void ShowDelegate(ref ReturnInfo retInfo, IntPtr records, int length);
private void RecordInfo(ref ReturnInfo retInfo, IntPtr records, int length)
{
// dgRecords数据类型是DataGridView,我的理解就是显示记录的表格视图
if (this.dgRecords.InvokeRequired)
{
// 这一句我不理解为什么要这样做,如果不加这一句,后面的显示就会出问题
this.dgRecords.Invoke(new ShowDelegate(RecodInfo), retInfo, records, length);
}
else
{
if (retInfo.ErrorCode != 0)
{
MessageBox.Show("获取记录失败!");
}
...... // 显示数据
}
}
这样的代码,如果在弹出窗口中点一、两次查询按钮不会出现问题,记录可以正常地显示出来,但是基本上点到第三次,就会弹出出错窗口了
我的理解是这样的:我还要用这个委托,但是C#的垃圾回收机制已经把它回收了,因此就会导致错误。
但我不会改这个问题,请教其他人,是这样修改的:
1、委托的定义放在这个显示窗口类的前面
2、增加回调函数的static 指针
static FuncQueryRecords pShowDelegate;
当然,现在看起来,这个回调函数的指针名字起得不好,因为一开始改代码的时候,不知道它到底是什么
3、这个显示窗口类初始化的地方,初始化这个回调函数指针
pShowDelegate = new FuncQueryRecords(RecodInfo);
4、点击“查询”按钮后,调用C++接口函数的方式改为
bool abc = ServerControl.QueryRecords(ref m_dev, ref query, pShowDelegate); //RecordInfo);
好,然后其他的地方不用改,这样再试,就不会有问题了。
但我目前还是只知其然,不知其所以然,先记下来吧,以后再学习。
在这个程序中,其实还有其他的一些回调函数的调用方式没有改,但是其他地方不会出问题,原因是其他地方的调用都是弹出窗口只显示一次,在弹出窗口中不会反复调用底层函数,问题就显现不出来了。

2258

被折叠的 条评论
为什么被折叠?



