📅  最后修改于: 2023-12-03 15:13:49.154000             🧑  作者: Mango
在 C# 的 Windows Presentation Foundation (WPF) 应用程序中,当一个线程尝试访问另一个线程所创建的控件时,就会抛出“线程访问异常”的错误。为了避免这种错误,必须使用 InvokeRequired
和 Invoke
方法。
InvokeRequired
属性用于判断当前线程是否是创建控件的线程。如果是,返回 false
,否则返回 true
。在访问控件之前,应该首先使用 InvokeRequired
属性。
if (control.InvokeRequired)
{
control.Invoke(new Action(() =>
{
// 在创建控件的线程上执行代码
}));
}
else
{
// 直接执行
}
Invoke
方法用于在创建控件的线程上执行代码。使用 Invoke
方法来调用带有参数的方法。使用 BeginInvoke
来调用异步方法。最后,使用 EndInvoke
来获取所返回的结果。
control.Invoke(new Action(() =>
{
// 在创建控件的线程上执行代码
}));
control.Invoke(new Action<string>((s) =>
{
// 在创建控件的线程上执行带字符串参数的代码
}), new object[] { "string parameter" });
var result = control.Invoke(new Func<string>(() =>
{
// 在创建控件的线程上执行有返回值的代码
return "result string";
}));
下面是一个简单的示例,展示了如何使用 InvokeRequired
和 Invoke
方法来更新 WPF 应用程序中的控件。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread t = new Thread(() =>
{
for (int i = 0; i < 100; i++)
{
if (label.Dispatcher.InvokeRequired)
{
label.Dispatcher.Invoke(new Action(() =>
{
label.Content = i.ToString();
}));
}
else
{
label.Content = i.ToString();
}
Thread.Sleep(100);
}
});
t.Start();
}
}
在这个示例中,单击按钮会创建一个新线程,并在新线程中更新标签控件的内容。在访问控件之前,首先通过 InvokeRequired
属性检查当前线程是否是创建控件的线程。如果不是,使用 Invoke
方法将一个委托传递给创建控件的线程,在创建控件的线程上更新控件的内容。最后在新线程上使用 Thread.Sleep
方法模拟长时间运行操作。