在c#windows窗体应用程序中使用showDialog()方法打开窗体后未触发串行端口事件

在c#windows窗体应用程序中使用showDialog()方法打开窗体后未触发串行端口事件,c#,winforms,serial-port,showdialog,C#,Winforms,Serial Port,Showdialog,事实上,当人们/顾客打电话到餐厅点菜时,我正在从com串口接收数据以获取电话/手机号码 第一次串行端口完全监听,然后windows窗体正确显示电话号码。要打开windows窗体,我必须使用this.showdialog()而不是this.show()。因为在当前表单后面已经打开了几个表单 问题发生在第一次显示对话框、串口未接听电话或串口功能触发后,并且表单未使用新的呼叫者电话号码更新 我知道这是因为使用了showdialog(),但我必须使用它。我记下了我用过的密码 private void

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

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

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

我知道这是因为使用了showdialog(),但我必须使用它。我记下了我用过的密码

private void FindCom()
{
尝试
{
//show(“称为Find Com”);
WriteLogFile(“文件:调用者”、“方法:FindCom”、“--FindCom调用--”);
字符串COM=RunProcess(“FindCOMET.exe”);//使用自动查找查找单元的
string[]COMPorts=COM.Split(“;”);//将自动查找字符串拆分为各个端口
COM=COMPorts[0];//选择第一个COM端口
//使用所有设置初始化COM端口。
serialPort=新的serialPort();
serialPort.PortName=COM;
serialPort.BaudRate=1200;
serialPort.DataBits=8;
serialPort.StopBits=停止位.1;
serialPort.Parity=奇偶校验.None;
serialPort.DataReceived+=新的SerialDataReceiveDevenHandler(this.serialPort\u DataReceived);
serialPort.ReadTimeout=100;//数据包结束超时通知需要
serialPort.Open();
}
捕获(例外情况除外)
{
//Show(“Exception1”+ex.Message.ToString());
LogFile.WriteLogFile(“文件:调用者”,“方法:FindCom”,“EM:+ex.Message.ToString());
}
//循环,直到用户按下一个键,然后退出
//System.Console.WriteLine(“按任意键退出”);
//Console.ReadKey();
}
//用于读取数据的变量
int[]缓冲区=新int[255];
int指针;
private void serialPort_DataReceived(对象发送方,System.IO.Ports.SerialDataReceivedEventArgs e)
{
尝试
{
//将所有当前缓冲区读入数组
for(int c=0;c!=serialPort.BytesToRead;c++)
{
缓冲区[指针]=serialPort.ReadByte();
指针++;
}
}
捕获(TimeoutException x)
{
尝试
{
COMET_数据cid=新COMET_数据(缓冲区);
//在这里输出数据或调用程序中的某些内容
字符串mobileNo=cid.getCIDNumber();
字符串电话=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.子串(1);
}
//MessageBox.Show(mobileNo.Substring(0,2)+“OF=>”+mobileNo);
如果(移动子串(0,2)=“07”)
{
//mobileNo=mobileNo;
Text=mobileNo;
lblMobileNo.Text=mobileNo;
}
其他的
{
电话=移动电话;
//MessageBox.Show(“电话:+电话”);
Text=电话;
lblMobileNo.Text=电话;
}
getName=cid.getCIDName();
}
其他的
{
lblCustomerName.Text=“不可用”;
txtbxMobileNo.Text=“保留”;
lblMobileNo.Text=“保留”;
}
//MessageBox.Show(mobileNo);
SaveCommetCaller(mobileNo);
//重置缓冲区指针和缓冲区
缓冲区=新整数[255];
指针=0;
//对于(int i=1;i>=0;i--)
isFormOpen=true;
this.ShowDialog();
serialPort.DiscardInBuffer();
//is_open=false;
}
捕获(例外情况除外)
{
LogFile.WriteLogFile(“文件:调用者”,“方法:DataReceived”,“EM:+ex.Message.ToString());
}
//serialPort.DataReceived+=新的SerialDataReceiveDevenHandler(this.serialPort\u DataReceived);
}
最后
{
//serialPort.DataReceived+=serialPort_DataReceived;
}
}
无论发生什么情况,ShowDialog()都会阻止您的应用程序。 我能取得的最好成绩可以在这里看到:

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

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);
    }
}
调用this.invokeIfrequeired()是为了避免跨线程问题,如下所示:

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();
        });
    }
}
呵呵
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();
        });
    }
}
private void button1_Click(object sender, EventArgs e)
{
    serialPort1.Close();  //  <---
    Form1 nextForm = new Form1();
    Hide();
    nextForm.ShowDialog();
    Close();
}