在 System.InvalidOperationException 中第一次偶然出现的“System.Windows.Forms.dll”类型的异常

时间:2022-08-22 20:32:10
本人在学习C#过程中试着实践做一个USB电话盒的二次开发.
厂家提供电话盒的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

#3


异常出现在这一名:this.textBox1.Text = "HI,HI!";

#4


异常出现在这一句:this.textBox1.Text = "HI,HI!";

#5


引用 1 楼 computerfox 的回复:
没有看到你这里有跨线程访问呀,如果是跨线程访问,请参考这个帖子吧:
http://topic.csdn.net/u/20100428/14/78736388-bb69-4c2d-8a1d-11df04a5d0f0.html


使用委托对this.textBox1赋值,可能回调函数Ubox_Event_CallBack是在DLL中新建的一个线程中运行的.

#6


问题已解决:
如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

#2


#3


异常出现在这一名:this.textBox1.Text = "HI,HI!";

#4


异常出现在这一句:this.textBox1.Text = "HI,HI!";

#5


引用 1 楼 computerfox 的回复:
没有看到你这里有跨线程访问呀,如果是跨线程访问,请参考这个帖子吧:
http://topic.csdn.net/u/20100428/14/78736388-bb69-4c2d-8a1d-11df04a5d0f0.html


使用委托对this.textBox1赋值,可能回调函数Ubox_Event_CallBack是在DLL中新建的一个线程中运行的.

#6


问题已解决:
如5楼所说,DLL中存在线程,必需安全调用窗体控件,具体参考(对 Windows 窗体控件进行线程安全调用):
http://msdn.microsoft.com/zh-cn/library/ms171728%28VS.80%29.aspx