What causes my UI to freeze when closing a serial port?(关闭串行端口时,是什么导致我的 UI 冻结?)
问题描述
我正在开发一个与串口相关的应用程序.在使用 SerialPort 的 DataReceived 事件时,我需要使用接收到的字节更新文本框:
I am working on a serial port related application. While using DataReceived event of SerialPort I need to update a textbox with the received bytes:
private void Connection_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    var data = Connection.ReadExisting();
    _readBuffer.Add(indata);
    Invoke(new EventHandler(AddReceivedPacketToTextBox));       
}
所以我使用 Invoke 来更新文本框.但是有一个大问题.当我尝试关闭连接时,我的 UI 被冻结,我认为这是因为 Invoke 可能正在做某事.
So I use Invoke to update the textbox. But there is a big problem. When I try to close connection, my UI gets freezed, I think this is becase Invoke is doing somehing perhaps.
一位朋友说我应该使用 RequiredInvoke,但我不知道他到底在说什么.如何在不搞乱调用和 UI 线程的情况下关闭连接?
A friend said I should use RequiredInvoke, but I have no idea what he ment really. How can I close the connection without messing up the invoke and UI thread?
这是我的关闭方法:
private void DisconnectFromSerialPort()
{
    if (Connection != null && Connection.IsOpen)
    {
        Connection.Close();            
    }
}
更新
正如汉斯所说,我将 Invoke 更改为 BeginInvoke 但现在更糟了,我的应用程序由于 InvalidOperationException 而停止工作,因为集合 _readBuffer 已修改(VS 中的细节是这样说的)
As Hans said I changed Invoke to BeginInvoke but now its a bit worse, my application stops working due to InvalidOperationException because the collection _readBuffer was modified (Thats what the detail says in VS)
这是我将文本添加到文本框的代码:
Here is my code for adding text to textbox:
private void AddReceivedPacketToTextBox(object sender, EventArgs e)
{
    foreach (var i in _readBuffer)
        tbIn.Text += string.Format("{0:X2} ", i);
    tbIn.Text += Environment.NewLine;
    ScrollToBottom(tbIn);
    label4.Text = _receivedPackets.ToString();
    _receivedPackets++;
    _readBuffer.Clear(); //Possibly because clearing collection gets out of sync with BeginInvoke??         
}
第二次更新
我仍然有问题,将 Invoke() 更改为 BeginInvoke 没有帮助.我还尝试添加断开连接以形成关闭事件 nu 成功...每当我关闭我的表单时,它都会获得库存(我的意思是它的父表单,因为这个可以访问串行端口的表单正在从另一个表单调用.
I still have the problem, changing the Invoke() to BeginInvoke didn;t help. I also tried to add disconnect to form closing event nu success...anytime I close my form it gets stock (I mean its parent form, because this form that has access to serialport is being called from another form`.
我的意思是我发现 UI 仅在 2 种情况下被锁定:如果我为调用 Connection.Close() 的按钮计时,如果我尝试关闭表单,父表单将抛出一些对象被释放的异常.
I mean I figured out that the UI gets locked only in 2 cases: If I clock a button which calls Connection.Close()  also if I try to close the form, the parent form will throw exception that some objects are disposed.
我从父表单中这样调用串行表单:
I call the serial form like this from the parent form:
public DebugForm DebugForm;
private void button1_Click(object sender, EventArgs e)
{
    if (DebugForm != null)
    {
        DebugForm.BringToFront();
        return;
    }
    DebugForm = new DebugForm();
    DebugForm.StartPosition = FormStartPosition.CenterScreen;
    DebugForm.Closed += delegate
                             {
                                 WindowState = FormWindowState.Normal;
                                 DebugForm = null;
                             };
    DebugForm.Show();
    WindowState = FormWindowState.Minimized; 
}
这会是问题吗?!
推荐答案
这个问题可以通过添加定时器来解决:
The problem could be solved by adding a timer:
  bool formClosing = false;
    private void Connection_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
      if (formClosing) return;
      _buffer = Connection.ReadExisting();
      Invoke(new EventHandler(AddReceivedPacketToTextBox));
    }
    protected override void OnFormClosing(FormClosingEventArgs e)
    {
      base.OnFormClosing(e);
      if (formClosing) return;
      e.Cancel = true;
      Timer tmr = new Timer();
      tmr.Tick += Tmr_Tick;
      tmr.Start();
      formClosing = true;
    }
    void Tmr_Tick(object sender, EventArgs e)
    {
      ((Timer)sender).Stop();
      this.Close();
    }
感谢 MSDN<的 JohnWein/a>
Thanks to JohnWein from MSDN
这篇关于关闭串行端口时,是什么导致我的 UI 冻结?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:关闭串行端口时,是什么导致我的 UI 冻结?
				
        
 
            
        - Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
 - C#MongoDB使用Builders查找派生对象 2022-09-04
 - 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
 - WebMatrix WebSecurity PasswordSalt 2022-01-01
 - 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
 - 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
 - 如何用自己压缩一个 IEnumerable 2022-01-01
 - C# 中多线程网络服务器的模式 2022-01-01
 - 输入按键事件处理程序 2022-01-01
 - MoreLinq maxBy vs LINQ max + where 2022-01-01
 
						
						
						
						
						
				
				
				
				