首页 >后端开发 >C++ >如何在 C# 中从单独的线程安全地更新 UI 控件以避免跨线程异常?

如何在 C# 中从单独的线程安全地更新 UI 控件以避免跨线程异常?

Linda Hamilton
Linda Hamilton原创
2025-01-23 02:26:10721浏览

How to Safely Update UI Controls from a Separate Thread in C# to Avoid Cross-Thread Exceptions?

避免 C# 中的跨线程异常:安全更新 UI 控件

问题: C# 应用程序在从主 UI 线程以外的线程更新 UI 控件时经常遇到“跨线程操作无效”异常。当在单独的线程中处理来自外部源(例如微控制器的 UART 端口)的数据时,通常会发生这种情况。

场景:想象一下微控制器通过 UART 发送温度数据。 您的 C# 应用程序在后台线程中接收此数据,但尝试使用温度值直接更新 TextBox 会引发异常。

根本原因: UI 控件绑定到它们创建的线程。 从另一个线程访问它们违反了此规则。

解决方案:利用调度程序

解决这个问题的关键是使用调度程序,这是一种确保 UI 更新发生在正确线程上的机制。 这涉及一个简单但有效的模式:

  1. 创建委托:定义一个委托来封装UI更新操作:

    <code class="language-csharp">delegate void SetTextCallback(string text);</code>
  2. 实现Update方法:该方法检查当前线程是否是UI线程。如果没有,它使用 Invoke 将更新编组到 UI 线程:

    <code class="language-csharp">private void SetText(string text)
    {
        if (this.textBox1.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.textBox1.Text = text;
        }
    }</code>
  3. 从后台线程更新:serialPort1_DataReceived 事件处理程序(或等效)中,接收数据后调用 SetText 方法:

    <code class="language-csharp">private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        string receivedData = serialPort1.ReadExisting();
        SetText(receivedData); 
    }</code>

这种方法可以确保所有 UI 更新都在主 UI 线程上安全地执行,从而防止跨线程异常。 InvokeRequired 检查可以有效处理更新已在正确线程上的情况,避免不必要的开销。

以上是如何在 C# 中从单独的线程安全地更新 UI 控件以避免跨线程异常?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn