1.Control.Invoke
Invoke 会导致线程的阻塞,但是是顺序执行的,
private void Form1_Load(object sender, EventArgs e)
{
listBox1.Items.Add("begin");
listBox1.Invoke(new Action(() => { listBox1.Items.Add("invoke"); }));
listBox1.Items.Add("after");
}
2.Control.BeginInvoke
BeginInvoke 同样会导致线程的阻塞,在执行完主线程(UI线程)后才会执行,
private void Form1_Load(object sender, EventArgs e)
{
listBox1.Items.Add("begin");
listBox1.BeginInvoke(new Action(() => { listBox1.Items.Add("begininvoke"); }));
listBox1.Items.Add("after");
}
若想要在线程执行结束之前执行 BeginInvoke,可以使用 EndInvoke,
private void Form1_Load(object sender, EventArgs e)
{
listBox1.Items.Add("begin");
var i = listBox1.BeginInvoke(new Action(() => { listBox1.Items.Add("begininvoke"); }));
listBox1.EndInvoke(i);
listBox1.Items.Add("after");
}
或者 BeginInvoke 会在一个 Invoke 调用前执行,
private void Form1_Load(object sender, EventArgs e)
{
listBox1.Items.Add("begin");
listBox1.BeginInvoke(new Action(() => { listBox1.Items.Add("begininvoke"); }));
listBox1.Invoke(new Action(() => { listBox1.Items.Add("invoke"); }));
listBox1.Items.Add("after");
}
Tips:
如果 Invoke 在支线程中定义调用,那么它同样会在主线程(UI线程)中执行,也会阻塞主线程和支线程;
如果 BeginInvoke 在支线程中定义调用,那么它也会在主线程(UI线程)中执行,也会阻塞主线程,但相对于支线程是异步的。
Invoke 和 BeginInvoke 的主要作用是在支线程中访问 UI 线程,
private System.Timers.Timer myTimer; private void Form1_Load(object sender, EventArgs e) { //窗体打开时创建定时器,并设置执行频率时间,会创建新线程 this.myTimer = new System.Timers.Timer(1000); //设置任务 this.myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed); this.myTimer.AutoReset = true; this.myTimer.Enabled = true; this.myTimer.Start(); } private void myTimer_Elapsed(object sender, ElapsedEventArgs e) { count++; label1.Invoke(new Action(() => { label1.Text = count.ToString() + "s"; })); }