Winform Invoke与BeginInvoke
BeginInvoke与Invoke
BeginInvoke与Invoke联系
Invoke和BeginInvoke方法由ISynchronizeInvoke接口提供,且都需要一个委托对象作为参数。主要用于子线程操作主线程UI的控件,修改控件属性等。
BeginInvoke与Invoke区别
- Invoke同步运行,会等待代码运行完之后返回,线程会阻塞。
- BeginInvoke异步运行,调用之后立即返回,不会等待修改控件代码执行完,不会阻塞。
BeginInvoke与Invoke使用场景
- 若后台线程在更新UI界面且不需要等待,则应该使用BeginInvoke方法进行异步操作。
- 若后台线程在更新UI界面并且需要等待,则应该使用Invoke方法进行同步操作。
BeginInvoke与Invoke软件中执行顺序
private Thread invokeThread;
private delegate void invokeDelegate();
private void StartMethod(){
//C代码段......
Control.Invoke(new invokeDelegate(invokeMethod));
//D代码段......
}
private void invokeMethod(){
//E代码段
}
private void butInvoke_Click(object sender, EventArgs e) {
//A代码段.......
invokeThread = new Thread(new ThreadStart(StartMethod));
invokeThread.Start();
//B代码段......
}
A——>(Start一开始B和StartMethod的C就同时执行)—->(C执行完了,不管B有没有执行 完,invokeThread把消息封送(invoke)给UI线程,然后自己等待)—->UI线程处理完butInvoke_Click消息后, 处理invokeThread封送过来的消息,执行invokeMethod方法,即代码段E,处理往后UI线程切换到invokeThread线程。
Task与Invoke和BeginInvoke之间的组合使用
//主线程点击按键
private void button1_Click(object sender, EventArgs e)
{
//子线程
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
t1++;
this.lblTask1.BeginInvoke(new MethodInvoker(() =>
{
lblTask1.Text = t1.ToString();
//在这里延时会阻塞主线程,导致界面卡顿,需要放在BeginInvoke外面
//Thread.Sleep(500);
}));
//在子线程延时等待,不阻塞主线程
Thread.Sleep(500);
}
});
}
由于Invoke和BeginInvoke都是操作的主线程,所以尽量避免在子线程调用Invoke和BeginInvoke方法里再放其他延时操作,这样会导致界面卡顿的现象。
C#窗体子线程调用主线程控件方法
Winform中子线程调用主线程控件方法
this.Invoke(new Action(() =>
{
//调用主线程控件
}));
this.BeginInvoke(new Action(() =>
{
//调用主线程控件
}));
WPF中子线程调用主线程控件方法
Application.Current.Dispatcher.Invoke(((Action)delegate ()
{
// 在主线程中执行需要操作的UI代码
}));
await Application.Current.Dispatcher.BeginInvoke(((Action)delegate ()
{
// 在主线程中执行需要操作的UI代码
}));
参考:
C# Invoke和BeginInvoke-CSDN博客
C#及WPF多线程定义和使用2(Task)_wpf task-CSDN博客