【问题标题】:serial port event not firing after opening the form using showDialog() method in c# windows form application在 c# windows 窗体应用程序中使用 showDialog() 方法打开窗体后未触发串行端口事件
【发布时间】:2019-12-14 06:32:54
【问题描述】:

实际上,当人们/顾客打电话到餐厅订购时,我正在从 com 串行端口接收数据以获取 电话/手机号码

第一次完美监听串行端口,然后 windows 窗体正确显示电话号码。要打开窗体,我必须使用 this.showdialog() 而不是 this.show()。因为在当前表单后面已经打开了几个表单。

问题出现在第一次显示对话框后,串口未监听电话或触发串口功能,并且表单未使用新的呼叫者电话号码更新。

我知道这是因为使用了 showdialog() 而发生的,但我必须使用它。我记下了我使用的代码..

private void FindCom()
        {

            try
            {
                //Messagebox.show("Called Find Com"); 
                LogFile.WriteLogFile("File:Caller", "Method:FindCom", "--FindCom Called--");
                string COM = RunProcess("FindCOMET.exe"); // Using the autofind to find the unit's
                string[] COMPorts = COM.Split(';'); // Split the AutoFind string into individual ports
                COM = COMPorts[0]; // Select the first COM port 
                // Initialise COM port with all settings.
                serialPort = new SerialPort();
                serialPort.PortName = COM;
                serialPort.BaudRate = 1200;
                serialPort.DataBits = 8;
                serialPort.StopBits = StopBits.One;
                serialPort.Parity = Parity.None;
                serialPort.DataReceived += new SerialDataReceivedEventHandler(this.serialPort_DataReceived);
                serialPort.ReadTimeout = 100; // Required for end of packet Timeout notification
                serialPort.Open();
            }
            catch (Exception ex)
            {
                //MessageBox.Show("Exception1"+ ex.Message.ToString());
                LogFile.WriteLogFile("File:Caller", "Method:FindCom", "EM: " + ex.Message.ToString());
            }
            // Loop until user presses a key then exit
            //System.Console.WriteLine("Press any key to exit");
            //Console.ReadKey();
        }

        // Variables for the data read
        int[] buffer = new int[255];
        int pointer;
        private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            try
            {
                // Read all the current buffer into the array
                for (int c = 0; c != serialPort.BytesToRead; c++)
                {
                    buffer[pointer] = serialPort.ReadByte();
                    pointer++;
                }
            }
            catch (TimeoutException x)
            {
                try
                {
                   
                    COMET_Data cid = new COMET_Data(buffer);
                    // Output the data or call something within your program here 
                    string mobileNo = cid.getCIDNumber();
                    string telePhone =string.Empty;
                    var getName = string.Empty;
                    if (mobileNo != null)
                    {
                        mobileNo = Regex.Replace(mobileNo, "[^0-9]+", string.Empty);
                       // MessageBox.Show("FullNumber" + mobileNo);
                        if (mobileNo[0] == '9')
                        {
                            mobileNo = mobileNo.Substring(1);
                        }
                        //MessageBox.Show(mobileNo.Substring(0, 2)+" OF =>"+ mobileNo);
                        if (mobileNo.Substring(0,2) == "07")
                        {
                            //mobileNo = mobileNo;
                            txtbxMobileNo.Text = mobileNo;
                            lblMobileNo.Text = mobileNo;
                        }
                        else
                        {
                            
                            telePhone = mobileNo;
                            //MessageBox.Show("telephone:" + telePhone);
                            txtbxTelephone.Text = telePhone;
                            lblMobileNo.Text = telePhone;
                        }
                        getName = cid.getCIDName();
                        
                    }
                    else
                    {
                        lblCustomerName.Text = "Not Available";
                        txtbxMobileNo.Text = "Withheld";
                        lblMobileNo.Text = "Withheld";
                    }


                    //MessageBox.Show(mobileNo); 
                    SaveCommetCaller(mobileNo);
                    // Reset the buffer pointer and buffer
                    buffer = new int[255];
                    pointer = 0;
                    //for (int i = 1; i >= 0; i--)

                    isFormOpen = true;
                    this.ShowDialog();
                    serialPort.DiscardInBuffer();
                    //is_open = false;
                }
                catch (Exception ex)
                {
                    LogFile.WriteLogFile("File:Caller", "Method:DataReceived", "EM: " + ex.Message.ToString());
                }
                //serialPort.DataReceived += new SerialDataReceivedEventHandler(this.serialPort_DataReceived);
            }
            finally
            {
               // serialPort.DataReceived += serialPort_DataReceived;
            }
        }

我想在表单仍处于打开状态时使用 showdialog() 方法从串行端口获取数据,而无需用户活动来关闭或隐藏表单。

【问题讨论】:

    标签: c# winforms serial-port showdialog


    【解决方案1】:

    无论如何,ShowDialog() 都会阻止您的应用程序。 我可以达到的最佳结果可以在这里观看:Dialogs video

    首先,将您的事件发射器放在单独的线程/任务中,并将事件发射器注入第一个表单:

    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
    
            var callReceiver = new CallReceiver();
    
            var thread = new Thread(callReceiver.WaitForCall);
            thread.Start();
    
            Application.Run(new Form1(callReceiver));
        }
    }
    
    public class CallReceiver
    {
        public event EventHandler<int> CallReceived;
    
        public void WaitForCall()
        {
            var i = 0;
            while (true)
            {
                Thread.Sleep(1000);
                OnCallReceived(i++);//Dummy event emitter
            }
        }
        protected virtual void OnCallReceived(int e)
        {
            CallReceived?.Invoke(this, e);
        }
    }
    

    第一个表单监听来电事件并在来电时创建一个对话框。事件发射器也被注入到第二个对话框中。 Form1.cs:

    public partial class Form1 : Form
    {
        private readonly CallReceiver _callReceiver;
        private DisplayCallForm _displayCallForm;
        public Form1(CallReceiver callReceiver)
        {
            _callReceiver = callReceiver;
            InitializeComponent();
    
            _callReceiver.CallReceived += CallReceiverOnCallReceived;
    
        }
    
        private void CallReceiverOnCallReceived(object sender, int i)
        {
    
            this.InvokeIfRequired(() =>
            {
                if (_displayCallForm == null)
                {
                    _displayCallForm = new DisplayCallForm(_callReceiver);
    
                    _displayCallForm.Show(this); //give "this" to show() to make sure the 
                                                 //new dialog is in foreground.
                }
            });
        }
    }
    

    this.InvokeIfRequired() 是为了避免跨线程问题,看起来像这样:

    static class Invoker
    {
        public static void InvokeIfRequired(this Control control, MethodInvoker action)
        {
            if (control.InvokeRequired)
            {
                control.Invoke(action);
            }
            else
            {
                action();
            }
        }
    }
    

    DisplayCallForm.cs:

    public partial class DisplayCallForm : Form
    {
        private readonly CallReceiver _callReceiver;
    
        public DisplayCallForm(CallReceiver callReceiver)
        {
    
            InitializeComponent();
            _callReceiver = callReceiver;
    
            _callReceiver.CallReceived += CallReceiverOnCallReceived;
        }
    
        private void CallReceiverOnCallReceived(object sender, int i)
        {
            this.InvokeIfRequired(() =>
            {
                label1.Text = i.ToString();
            });
        }
    }
    

    希望这会有所帮助。

    【讨论】:

    • 您好 Saven Bardos,非常感谢您的帮助。我们解决了这个问题。我们使用 this.InvokeIfRequired() 函数来显示表单,我们从父表单调用表单。
    【解决方案2】:

    我遇到了同样的问题,解决起来非常简单,我没有调用“serialPort1.Close();”在我收到数据后,而是在我的情况下返回主页的按钮中:

    private void button1_Click(object sender, EventArgs e)
    {
        serialPort1.Close();  //  <---
        Form1 nextForm = new Form1();
        Hide();
        nextForm.ShowDialog();
        Close();
    }   
    

    这让我可以在 winforms 之间切换并保持串口 1 的功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-06
      • 1970-01-01
      • 1970-01-01
      • 2021-04-30
      • 2011-08-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多