从串行端口获取数据后打开新表单
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();
}
}
我 运行 在从条形码扫描仪获取一些数据后尝试打开新表单时遇到问题。这个想法是有一个主窗体,打开 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();
}
}