You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何跨线程更新文本框以实时显示计量秤读取值?

解决WinForms跨线程更新TextBox及实时读取计量秤数据的问题

问题分析

你当前存在两个核心问题:

  • 非UI线程(Socket回调线程)直接操作textBox1触发跨线程安全错误
  • 仅在点击按钮时更新一次UI,无法实时同步计量秤的最新数据

解决方案

1. 封装线程安全的UI更新方法

WinForms要求所有UI操作必须在UI线程执行,因此需要专门写一个安全更新TextBox的方法:

// 线程安全更新TextBox的工具方法
private void UpdateTextBoxSafely(string text)
{
    if (textBox1.InvokeRequired)
    {
        // 当前非UI线程,委托UI线程执行更新
        textBox1.Invoke(new Action<string>(UpdateTextBoxSafely), text);
    }
    else
    {
        // UI线程直接更新文本
        textBox1.Text = text;
    }
}

2. 修改数据接收回调,实现实时更新

在OnRecievedData方法中,删除直接赋值textBox1.Text的代码,替换为调用上面的安全更新方法:

修改OnRecievedData中的关键逻辑:

if (sRecieved.IndexOf("\n") != -1)
{
    // 触发自定义数据接收事件
    if (ReceivedData != null)
        ReceivedData(this._Mensagem);

    this._LastReadValue = this._Mensagem;

    // 替换直接赋值,调用安全更新方法
    UpdateTextBoxSafely(this._LastReadValue);

    this._Mensagem = "";
}

3. 调整初始更新逻辑

原来updateGUI方法里的textBox1.Text = this._LastReadValue;可以移除,因为Socket连接成功后,后续的实时数据会通过回调自动触发UI更新。如果需要在连接成功时显示初始值,可以在OnConnect的成功分支里调用UpdateTextBoxSafely(this._LastReadValue)。

完整修改后的关键代码片段

// 新增线程安全更新方法
private void UpdateTextBoxSafely(string text)
{
    if (textBox1.InvokeRequired)
    {
        textBox1.Invoke(new Action<string>(UpdateTextBoxSafely), text);
    }
    else
    {
        textBox1.Text = text;
    }
}

private void OnRecievedData(IAsyncResult ar)
{
    Socket sock = (Socket)ar.AsyncState;

    if (m_sock.Connected == false)
        return;

    try
    {
        int nBytesRec = sock.EndReceive(ar);

        if (nBytesRec > 0)
        {
            string sRecieved = Encoding.ASCII.GetString(m_byBuff, 0, nBytesRec);
            this._Mensagem = sRecieved;

            if (sRecieved.IndexOf("\n") != -1)
            {
                if (ReceivedData != null)
                    ReceivedData(this._Mensagem);

                this._LastReadValue = this._Mensagem;
                // 安全触发UI更新
                UpdateTextBoxSafely(this._LastReadValue);

                this._Mensagem = "";
            }

            SetupRecieveCallback(sock);
        }
        else
        {
            sock.Shutdown(SocketShutdown.Both);
            sock.Close();
            throw new Exception($"Client {sock.RemoteEndPoint}, disconnected");
        }
    }
    catch (Exception ex)
    {
        sock.Close();
    }
}

void updateGUI()
{
    Connect();
    // 移除单次赋值,由Socket回调实时更新UI
}

说明

  • 线程安全方法UpdateTextBoxSafely通过InvokeRequired判断线程环境,非UI线程时将更新操作委托给UI线程执行,彻底解决跨线程错误。
  • 每次Socket收到完整的计量秤数据(以\n结尾)时,都会自动触发UI更新,实现数据实时同步。
  • 点击按钮建立连接后,Socket会持续监听计量秤数据,后续所有新数据都会自动更新到TextBox中,不再是单次更新。

内容的提问来源于stack exchange,提问作者Hugo Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 04:40:23