1.Control下调用
1.1 在主线程调用
listBox1.Items.Add("--begin--");
listBox1.Invoke(new Action(() =>
{
listBox1.Items.Add("Invoke");
}));
Thread.Sleep(1000);
listBox1.Items.Add("--end--");
listBox1.Items.Add("--begin--");
var bi = listBox1.BeginInvoke(new Action(() =>
{
//Thread.Sleep(10000);
listBox1.Items.Add("BeginInvoke");
}));
Thread.Sleep(1000);
listBox1.Items.Add("--end--");
此时两种情况都会卡死UI的
在主线程中直接调用Invoke、BeginInvoke、EndInvoke都会造成阻塞
1.2 在子线程调用
private void Button1_Click(object sender, EventArgs e)
{
Thread.CurrentThread.Name = "Main";
listBox1.Items.Add("--begin--");
new Thread(() =>
{
Thread.CurrentThread.Name = "ThreadInvoke";
string temp = "Before!";
listBox1.Invoke(new Action(() =>
{
Thread.Sleep(10000);
this.listBox1.Items.Add(temp += "Invoke!" + Thread.CurrentThread.Name);
}));
temp += "After!";
}).Start();
listBox1.Items.Add("--end--");
}
1.listBox1.Invoke的委托其实也在主线程中执行
2.Invoke在支线程中调用也会阻塞主线程UI。
3.Invoke还会阻塞支线程。(因为输出结果中没有出现After)
private void Button1_Click(object sender, EventArgs e)
{
Thread.CurrentThread.Name = "Main";
listBox1.Items.Add("--begin--");
new Thread(() =>
{
Thread.CurrentThread.Name = "ThreadBeginInvoke";
string temp = "Before!";
listBox1.BeginInvoke(new Action(() =>
{
Thread.Sleep(10000);
this.listBox1.Items.Add(temp += "Invoke!" + Thread.CurrentThread.Name);
}));
temp += "After!";
}).Start();
listBox1.Items.Add("--end--");
}
1.BeginInvoke在主线程中执行。
2.BeginInvoke在支线程中调用也会阻塞主线程。
3.BeginInvoke相对于支线程是异步的,即没有阻塞支线程
总结:
Control的Invoke和BeginInvoke的委托方法是在主线程,即UI线程上执行。(也就是说如果你的委托方法用来取花费时间长的数据,然后更新界面什么的,千万别在主线程上调用Control.Invoke和Control.BeginInvoke,因为这些是依然阻塞UI线程的,造成界面的假死)
Invoke会阻塞主支线程,BeginInvoke只会阻塞主线程,不会阻塞支线程!因此BeginInvoke的异步执行是指相对于支线程异步,而不是相对于主线程异步。
2.Delegate调用
delegate void xDel(int i);
private void Button1_Click(object sender, EventArgs e)
{
Thread.CurrentThread.Name = "Main";
listBox1.Items.Add("--begin--");
xDel xd = new xDel(t =>
{
//Thread.Sleep(t);
//listBox1.BeginInvoke(new Action(() =>
//{
// listBox1.Items.Add("Invoke");
//}));
Thread.CurrentThread.Name = "ThreadBeginInvoke";
string temp = "Before!";
listBox1.BeginInvoke(new Action(() =>
{
Thread.Sleep(10000);
this.listBox1.Items.Add(temp += "Invoke!" + Thread.CurrentThread.Name);
}));
temp += "After!";
});
xd.BeginInvoke(3000, null, null);
listBox1.Items.Add("--end--");
}
其实这种情况跟上面new Thread是一样的,委托的beginInvoke也是开了一个线程
注:
在WPF中,写法又有点不一样,要Dispatcher.Invoke
listBox1.Items.Add("--begin--");
listBox1.Dispatcher.Invoke(new Action(() =>
{
listBox1.Items.Add("Invoke");
}));
Thread.Sleep(1000);
listBox1.Items.Add("--end--");
参考:
https://www.cnblogs.com/wangshenhe/archive/2012/05/25/2516842.html
https://www.cnblogs.com/small-code/p/5732116.html
https://blog.csdn.net/goodshot/article/details/6157529
https://www.cnblogs.com/c2303191/articles/826571.html
https://blog.csdn.net/sinat_23338865/article/details/52596818