从串行端口获取数据后打开新表单

Opening new Form after getting data from serialPort

我 运行 在从条形码扫描仪获取一些数据后尝试打开新表单时遇到问题。这个想法是有一个主窗体,打开 serialPort 并使用 DataReceived 事件读取数据。当那一刻发生时,我想打开新表单并将该数据传递给它。 (理想状态是通过 serialPort,这样它也可以在那里运行)

    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {

        string barcode = serialPort1.ReadExisting();
        if (this.InvokeRequired)
        {
            this.Invoke(new SetCallBack(SetText), new object[] { barcode });
        }

    }
    delegate void SetCallBack(string text);
    private void SetText(string text)
    {
            Form2 frm = new Form2(text, serialPort1);
            frm.ShowDialog();
            serialPort1.DiscardInBuffer();
    }

一次或两次它工作正常,但之后控件冻结。当我将代码更改为

frm.Show();

它工作没有问题(或者至少它们是不可见的)。由于 .ShowDialog(),我在那里遇到了一些死锁吗?

//请注意,我还从数据库中获取了一些此处未显示的数据,但这也可能导致问题

有人建议我不要使用 DataReceive 事件,而是设置一个定时器(~250 毫秒)并检查 ByteToRead 属性,但我 运行 遇到了同样的问题。

我也会坚持使用 Form.Show() 的工作版本,但不幸的是我需要该对话框是模态的。

如果您对问题所在有任何想法,我将非常高兴。 提前致谢!

可能是某种死锁,因为您在 Form2 中使用串行端口。 您能举个例子说明您如何处理表单中的 serialPort1 吗? 事实上,您的表单有时会冻结也是一个很好的迹象。

如果可能,请将必要的数据提交给您的第二张表格。

Form2 frm = new Form2(text);

如果这不可能,您必须检查您的所有方法是否真的是线程安全的。 (=> https://en.wikipedia.org/wiki/Thread_safety)

调用显示对话框后,您会得到一个对话框结果。此对话框结果阻止您创建另一个对话框,直到您处理它(如解释的 here)。

您应该手动处理它或将对话调用置于 using 调用中

    private void SetText(string text)
        {
                using (Form2 frm = new Form2(text, serialPort1))
                {
                        frm.ShowDialog();
                }
                serialPort1.DiscardInBuffer();
        }

private void SetText(string text)
    {
            Form2 frm = new Form2(text, serialPort1);
            frm.ShowDialog();
            frm.Dispose();
            serialPort1.DiscardInBuffer();
    }

我认为 GC 应该在不再使用该对话框时为您执行此操作。但我不确定调用时效果如何。

编辑 有点赌博,但试试这个:

private object mScanLock = new object();
private void SetText(string text)
        {
           lock(mScanLock) {
                Form2 frm = new Form2(text, serialPort1);
                frm.ShowDialog();
                frm.Dispose();
                serialPort1.DiscardInBuffer();
              }
        }