在WinForm或WPF中,默认只允许在创建控件的线程(一般为UI线程)中访问控件,如果我们想在子线程中访问UI线程的资源,需要做特殊处理
WinForm处理方式
WinForm当中,我们有两种方式来解决这个问题。我们可以在窗体构造函数当中添加CheckForIllegalCrossThreadCalls = false,禁止窗体进行非法跨线程调用的校验,只是屏蔽了非法校验,并没有真正解决问题,不推荐使用
我们可以使用一下方式解决WinForm中UI资源的跨线程调用问题
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(() => ChangeText());
thread.Start();
}
private void ChangeText()
{
Random rdm = new Random();
string num = rdm.Next().ToString();
//当前线程是创建此控件的线程
if (txt.InvokeRequired)
txt.Invoke(new Action<string>(s => txt.Text = s), num);
//当前线程不是创建此控件的线程
else
txt.Text = num;
}
WPF程序的处理方式
每个WPF应用程序中都有一个Dispatcher类对象,该类对象是一个队列,用来保存应用程序主线程中的所有正在执行的工作。为了避免多个线程通过访问同一WPF控件的相同属性,其他线程应该请求主线程代表它执行访问控件属性的操作,即把访问主线程的方法放到主线程的Dispather类的对象中排队
private void Button_Click(object sender, RoutedEventArgs e)
{
Thread thread = new Thread(() => ChangeText());
thread.Start();
}
private void ChangeText()
{
Random rdm = new Random();
string num = rdm.Next().ToString();
//当前线程不是主线程
if (Dispatcher.Thread != Thread.CurrentThread)
{
Dispatcher.Invoke(new Action<string>(s => txt.Text = s), num);
}
//当前线程是主线程
else
txt.Text = num;
}
|