在 WinForm 应用程序中,当后台线程需要更新界面上的 UI 元素时,需要注意跨线程访问 UI 元素的问题。因为 UI 元素只能由创建它的主线程访问和修改,如果在其他线程中访问,程序将抛出一个“ System.InvalidOperationException ”异常。下面介绍两种常见的跨线程访问 UI 元素的办法。
方法一、使用 Control.Invoke()
Control.Invoke() 方法是常规方法之一,它与创建 UI 线程相同的线程进行同步。以下是对该方法的方法说明:
public IAsyncResult Invoke(Delegate method);
public IAsyncResult Invoke(Delegate method, object[] args);
其中,第一个参数 “method” 是Delegate类型,它指示要在与控件关联的窗口句柄的创建线程上调用的方法。第二个可选参数“args” 是对要调用的方法的参数进行的对象数组。
以下是使用 Control.Invoke() 的示例:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(ThreadProc));
t.Start();
}
private void ThreadProc()
{
this.Invoke(new Action(() =>
{
label1.Text = "正在处理...";
}));
// 模拟线程操作
Thread.Sleep(5000);
this.Invoke(new Action(() =>
{
label1.Text = "处理完成!";
}));
}
}
在这个示例中,当单击按钮时,将启动一个新的线程 ThreadProc()。该方法使用 Control.Invoke() 方法更新 label1 上的文本。
方法二、使用 Control.BeginInvoke()
Control.BeginInvoke() 方法比 Control.Invoke() 方法更常见,它是一个异步方法,它允许后台线程继续工作,而不必等待 UI 元素更新。以下是对该方法的方法说明:
public IAsyncResult BeginInvoke(Delegate method);
public IAsyncResult BeginInvoke(Delegate method, object[] args);
其中,第一个参数 “method” 是Delegate类型,它指示要在与控件关联的窗口句柄的创建线程上调用的方法。第二个可选参数“args” 是对要调用的方法的参数进行的对象数组。
以下是使用 Control.BeginInvoke() 的示例:
public partial class Form1 : Form
{
delegate void SetTextCallback(string text);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(ThreadProc));
t.Start();
}
private void ThreadProc()
{
SetText("正在处理...");
//模拟线程操作
Thread.Sleep(5000);
SetText("处理完成!");
}
private void SetText(string text)
{
if (label1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.BeginInvoke(d, new object[] { text });
}
else
{
this.label1.Text = text;
}
}
}
在这个示例中,当单击按钮时,将启动一个新的线程 ThreadProc()。该方法使用 Control.BeginInvoke() 方法更新 label1 上的文本。首先,该示例定义了一个委托 SetTextCallback 和一个 SetText() 方法,用于通过 label1 更新文本。该方法检查 invokeRequired 属性是否为 true,如果为 true,则使用Control.BeginInvoke() 把 SetText() 方法异步投递到 UI 线程中。在其他情况下,直接在当前线程中更新标签的文本。
以上两个方法都可以用来解决在 WinForm 中如何跨线程访问 UI 元素的问题。其中,使用 Control.BeginInvoke() 方法比较常见,因为使用该方法不会阻塞后台线程。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Winform中如何跨线程访问UI元素 - Python技术站