在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 测试通过3
this.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日
本文介绍了如何在WindowsForms中处理TextBox控件的线程安全问题,通过创建SafeTextBox类和使用Invoke或BeginInvoke方法确保在非UI线程更新内容时不会引发异常。
https://blog.youkuaiyun.com/anlog/article/details/136320466?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22136320466%22%2C%22source%22%3A%22anlog%22%7D
915

被折叠的 条评论
为什么被折叠?



