在Windows Forms中,由于UI控件不是线程安全的,直接跨线程访问和修改UI控件通常会导致不可预测的行为或异常。TextBox 控件同样不能直接从非创建它的线程进行写入。为了安全地在不同线程间更新 TextBox 控件的内容,你可以使用控件的 Invoke 方法或 BeginInvoke 方法来在控件的拥有线程(通常是主UI线程)上执行操作。
以下是一个扩展 TextBox 控件的简单示例,它提供了一个线程安全的方法来更新文本内容:
using System;  
using System.Threading;  
using System.Windows.Forms;  public class SafeTextBox : TextBox  
{  // 委托,用于定义在UI线程上执行的方法签名  public delegate void SafeSetTextCallback(string text);  // 公有方法,用于安全地设置TextBox的Text属性  public void SafeSetText(string text)  {  // 检查调用线程是否是创建控件的线程  if (this.InvokeRequired){// 如果不是,则使用Invoke在正确的线程上执行  //方法1 测试通过1//SafeSetTextCallback d = new SafeSetTextCallback(SafeSetText);//this.Invoke(d, new object[] { text });//方法2  测试通过2//Action<string> dlg = new Action<string>(SafeSetText);//this.Invoke(dlg, text);//方法3  测试通过3this.Invoke(new Action<string>(SafeSetText), text);}else  {  // 如果是,则直接设置Text属性  this.Text = text;  }  }  
}  // 使用示例  
public partial class MainForm : Form  
{  private SafeTextBox safeTextBox;  public MainForm()  {  InitializeComponent();  safeTextBox = new SafeTextBox();  safeTextBox.Dock = DockStyle.Fill;  this.Controls.Add(safeTextBox);  // 在一个后台线程中更新TextBox  Task.Run(() =>  {  // 模拟一些工作  Thread.Sleep(1000);  // 安全地更新TextBox的文本  safeTextBox.SafeSetText("这是从后台线程安全地写入的文本!");  });  }  
}在上面的代码中,SafeTextBox 类继承自 TextBox 类,并添加了一个名为 SafeSetText 的方法。这个方法接受一个字符串参数,并使用一个委托来在UI线程上安全地设置 TextBox 的 Text 属性。如果调用 SafeSetText 的线程不是创建 TextBox 的线程(即主UI线程),则通过 Invoke 方法在正确的线程上执行该操作。如果是主UI线程,则直接设置 Text 属性。
使用 SafeTextBox 控件与使用普通的 TextBox 控件类似,但是你可以通过调用 SafeSetText 方法来安全地在后台线程中更新其文本内容。
注意:虽然上面的代码示例适用于Windows Forms应用程序,但如果你正在使用WPF或其他类型的UI框架,实现方式可能会有所不同。在WPF中,你通常会使用 Dispatcher.Invoke 或 Dispatcher.BeginInvoke 来在UI线程上执行操作。
特此记录
anlog
2024年2月23日