厂家提供电话盒的DLL,并提供说明.
编写的思路是:先利用回调函数调用DLL中的打开设备函数,再利用回调函数实现对USB电话盒的各类事件作出响应.
回调和事件响应都已成功,但想在事件响应中对Form1窗口中的控件外观进行控制,运行没问题,但在输出窗口中出现"在 System.InvalidOperationException 中第一次偶然出现的“System.Windows.Forms.dll”类型的异常",Textbox1中的内容无改变.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace USBtelephone
{
public partial class Form1 : Form
{
UsbBox myUsBox = new UsbBox();
public Form1()
{
InitializeComponent();
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
myUsBox.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
UboxEventsubscribe();//USB电话盒的各类事件订阅
}
private void UboxEventsubscribe()//USB电话盒的各类事件订阅
{
myUsBox.TelephoneOffLine += new EventHandler(myUsBox_TelephoneOffLine);//订阅摘机事件
myUsBox.TelelphoneShutDown+=new EventHandler(myUsBox_TelelphoneShutDown);//订阅挂机事件
}
void myUsBox_TelephoneOffLine(object sender, EventArgs e)
{
Debug.WriteLine("电话机摘机了(In Form)");
}
private void myUsBox_TelelphoneShutDown(object sender, EventArgs e)//响应电话机挂机事件
{
Debug.WriteLine("挂机了(in Form)");
this.textBox1.Text = "HI,HI!";
}
private void Form1_Activated(object sender, EventArgs e)
{
myUsBox.Open();
}
}
}
以下是UsbBox 类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;//这句一定要
using System.Diagnostics;
namespace USBtelephone
{
class UsbBox
{
#region 定义枚举类型UBOX_EVENT_Enum
enum UBOX_EVENT_Enum
{
UBOX_EVENT_LINE_RINGING = 11, //振铃,硬件LED亮
UBOX_EVENT_LINE_HOOK_OFF = 12, //摘机,硬件LED亮
UBOX_EVENT_RING_CANCEL = 15, //振铃取消,当末次振铃停止超过6秒,则触发此事件,
UBOX_EVENT_LINE_HOOK_UP = 30, //挂机
}//end UBOX_EVENT_Enum
#endregion
private int UsbBoxHwnd;//设备名柄
#region 各类事件定义
public event EventHandler LineRing;//线路振铃事件
public event EventHandler RING_CANCEL;//振铃取消,当末次振铃停止超过6秒,则触发此事件
public event EventHandler TelelphoneShutDown;//挂机事件
public event EventHandler TelephoneOffLine;//摘机事件
#endregion
#region Dll各类命令定义
//Dll各类命令定义
//------------------------------------------------------------------------------------------------
[DllImport(@"E:\UsbTel\phonic_ubox.dll")]
static extern int ubox_open(UBoxEventNotifyProc proc, int mode);//UBoxEventNotifyProc回调函数
[DllImport(@"E:\UsbTel\phonic_ubox.dll")]
static extern void ubox_close();
[DllImport(@"E:\UsbTel\phonic_ubox.dll")]
static extern int ubox_get_work_mode();
[DllImport(@"E:\UsbTel\phonic_ubox.dll")]
static extern int ubox_send_dtmf(int uboxHnd, string dmftfstring);
//---------------------------------------------------------------------------------------------
#endregion
//定义Usb电话盒的二次开发包的回调函数委托
public delegate void UBoxEventNotifyProc(int uboxHnd, int eventID, uint param1, uint param2, uint param3, uint param4);//param1~parm4代表各类返回值
#region usb电话盒回调函数
//usb电话盒回调函数
unsafe private void Ubox_Event_CallBack(
int uboxHnd, int eventID, uint param1,
uint param2, uint param3, uint param4)//USB盒回调函数
{
EventArgs e = new EventArgs();
UBOX_EVENT_Enum myUboxEven = (UBOX_EVENT_Enum)eventID;
switch (myUboxEven)//对回调的eventID值产生各类事件
{
case UBOX_EVENT_Enum.UBOX_EVENT_LINE_RINGING://=11振铃
if (LineRing != null) LineRing(this, e);//发出振铃事件
break;
case UBOX_EVENT_Enum.UBOX_EVENT_RING_CANCEL://=15 振铃取消,当末次振铃停止超过6秒触发此事件
if (RING_CANCEL != null) RING_CANCEL(this, e);//发出振铃取消事件
break;
case UBOX_EVENT_Enum.UBOX_EVENT_LINE_HOOK_UP://挂机
if (TelelphoneShutDown != null) TelelphoneShutDown(this, e);//发出挂机事件
break;
case UBOX_EVENT_Enum.UBOX_EVENT_LINE_HOOK_OFF://摘机
if (TelephoneOffLine != null) TelephoneOffLine(this, e);//发出摘机事件
break;
}
}//end Ubox_Event_CallBack
#endregion
public void Open()
{
UBoxEventNotifyProc myUBoxEvNoProc = new UBoxEventNotifyProc(Ubox_Event_CallBack);//定义委托变量
int resultOpen = ubox_open(myUBoxEvNoProc, 0);//打开设备,并付予委托
Debug.WriteLine(string.Format("Open result={0}", resultOpen));
}//end Open
public void Close()
{
ubox_close();
}
}//end class Usbbox
}
是不是有交叉线程调用问题,请高手指教,谢谢!
6 个解决方案
#1
没有看到你这里有跨线程访问呀,如果是跨线程访问,请参考这个帖子吧:
http://topic.csdn.net/u/20100428/14/78736388-bb69-4c2d-8a1d-11df04a5d0f0.html
http://topic.csdn.net/u/20100428/14/78736388-bb69-4c2d-8a1d-11df04a5d0f0.html
#3
异常出现在这一名:this.textBox1.Text = "HI,HI!";
#4
异常出现在这一句:this.textBox1.Text = "HI,HI!";
#5
使用委托对this.textBox1赋值,可能回调函数Ubox_Event_CallBack是在DLL中新建的一个线程中运行的.
#6
问题已解决:
如5楼所说,DLL中存在线程,必需安全调用窗体控件,具体参考(对 Windows 窗体控件进行线程安全调用):
http://msdn.microsoft.com/zh-cn/library/ms171728%28VS.80%29.aspx
如5楼所说,DLL中存在线程,必需安全调用窗体控件,具体参考(对 Windows 窗体控件进行线程安全调用):
http://msdn.microsoft.com/zh-cn/library/ms171728%28VS.80%29.aspx
#1
没有看到你这里有跨线程访问呀,如果是跨线程访问,请参考这个帖子吧:
http://topic.csdn.net/u/20100428/14/78736388-bb69-4c2d-8a1d-11df04a5d0f0.html
http://topic.csdn.net/u/20100428/14/78736388-bb69-4c2d-8a1d-11df04a5d0f0.html
#2
#3
异常出现在这一名:this.textBox1.Text = "HI,HI!";
#4
异常出现在这一句:this.textBox1.Text = "HI,HI!";
#5
使用委托对this.textBox1赋值,可能回调函数Ubox_Event_CallBack是在DLL中新建的一个线程中运行的.
#6
问题已解决:
如5楼所说,DLL中存在线程,必需安全调用窗体控件,具体参考(对 Windows 窗体控件进行线程安全调用):
http://msdn.microsoft.com/zh-cn/library/ms171728%28VS.80%29.aspx
如5楼所说,DLL中存在线程,必需安全调用窗体控件,具体参考(对 Windows 窗体控件进行线程安全调用):
http://msdn.microsoft.com/zh-cn/library/ms171728%28VS.80%29.aspx