我使用VC创建了一个DLL文件,这个DLL文件唯一特殊地方是它创建一个线程,该线程可以回调C#代码?
问题出现在回调几次后C#程序出错挂掉。VC 程序如下:Test.DLLtypedef int(*InputFunction)();
typedef int(*OutputFunction)();
//全局变量
InputFunction SpexInputFunction=NULL;
OutputFunction SpexOutputFunction=NULL;
int IsStop=0;
HANDLE spexthread=NULL;
DWORD spexthreadID;static DWORD WINAPI ThreadProc(LPVOID lpParam)
{
while(IsStop ==1)
{
Sleep(5000);
SpexInputFunction();
}
SpexOutputFunction();
return 0;
}
//初始化函数指针
int Start(SpeexInputFunction inputfun,SpeexOutputFunction outputfun)
{ SpexInputFunction=inputfun;
SpexOutputFunction=outputfun;
IsStop=1;
spexthread=CreateThread(NULL,NULL,ThreadProc,NULL,0,&spexthreadID);
}
void SpeexNativeStop()
{
IsStop=0;
WaitForSingleObject(spexthread,INFINITE);
CloseHandle(spexthread);
}C#调用 Start C语言创建一个线程,该线程回调C#中的函数。C#代码如下:
public delegate int DelegateInput();
public delegate int DelegateOutput();
public partial class Form1 : Form
{ [DllImport("Test.DLL")]
internal static extern int Start(DelegateSpeexInput inputfucntion,DelegateSpeexOutput outputfunction);
[DllImport("Test.DLL")]
internal static extern int Stop(); public static int Input()
{
//MessageBox.Show("InputFunction");
return 0;
}
public static int OutPut()
{
// MessageBox.Show("OutPutFunction");
return 0;
} private DelegateInput spexinput = new DelegateInput(Input);
private DelegateOutput spexoutput = new DelegateOutput(OutPut); public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
int result=Start(spexinput, spexoutput);
//MessageBox.Show(result.ToString());
} private void button2_Click(object sender, EventArgs e)
{
Stop();
}
}主要代码我已经写出来了,大家一起探讨下。现象是C创建的线程头几次回调是没有问题的,回调次数多了C#主程序就挂掉了。错误提示:中的 0x0365bc00 处未处理的异常: 0xC0000005: 写入位置 0x03770000 时发生访问冲突。
问题出现在回调几次后C#程序出错挂掉。VC 程序如下:Test.DLLtypedef int(*InputFunction)();
typedef int(*OutputFunction)();
//全局变量
InputFunction SpexInputFunction=NULL;
OutputFunction SpexOutputFunction=NULL;
int IsStop=0;
HANDLE spexthread=NULL;
DWORD spexthreadID;static DWORD WINAPI ThreadProc(LPVOID lpParam)
{
while(IsStop ==1)
{
Sleep(5000);
SpexInputFunction();
}
SpexOutputFunction();
return 0;
}
//初始化函数指针
int Start(SpeexInputFunction inputfun,SpeexOutputFunction outputfun)
{ SpexInputFunction=inputfun;
SpexOutputFunction=outputfun;
IsStop=1;
spexthread=CreateThread(NULL,NULL,ThreadProc,NULL,0,&spexthreadID);
}
void SpeexNativeStop()
{
IsStop=0;
WaitForSingleObject(spexthread,INFINITE);
CloseHandle(spexthread);
}C#调用 Start C语言创建一个线程,该线程回调C#中的函数。C#代码如下:
public delegate int DelegateInput();
public delegate int DelegateOutput();
public partial class Form1 : Form
{ [DllImport("Test.DLL")]
internal static extern int Start(DelegateSpeexInput inputfucntion,DelegateSpeexOutput outputfunction);
[DllImport("Test.DLL")]
internal static extern int Stop(); public static int Input()
{
//MessageBox.Show("InputFunction");
return 0;
}
public static int OutPut()
{
// MessageBox.Show("OutPutFunction");
return 0;
} private DelegateInput spexinput = new DelegateInput(Input);
private DelegateOutput spexoutput = new DelegateOutput(OutPut); public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
int result=Start(spexinput, spexoutput);
//MessageBox.Show(result.ToString());
} private void button2_Click(object sender, EventArgs e)
{
Stop();
}
}主要代码我已经写出来了,大家一起探讨下。现象是C创建的线程头几次回调是没有问题的,回调次数多了C#主程序就挂掉了。错误提示:中的 0x0365bc00 处未处理的异常: 0xC0000005: 写入位置 0x03770000 时发生访问冲突。
就是这个样子,调用几次,就挂掉。
最后也没找到什么好办法,不过项目最后不做了。你试试,GC.KeepAlive(object),这个事件,当时是没有找到这个方法,也没有测试。你试试看行不行。
添加 WINAPI 。
或者修改 C# 中的委托。
设置 CallingConvention = Cdecl。
如果是因为字节不对其造成的话,那就第一次回调时候就该失败了,可是在成功回调几次C#线程挂掉了,C创建的线程还一直运行着,这时候C#主界面就未响应了。有人说delegrate创建的函数指针和C语音中的函数指针是不一样的,由于对两个语音汇编原理不太清楚,我也不太确定。有时间大家可以尝试下。
我现在改变思路了,用C#中线程循环调用DLL中代码,这样托管线程安全些。