C#中Invoke 和 BeginInvoke 的真正涵義
BeginInvoke 方法真的是新開一個(gè)線程進(jìn)行異步調(diào)用嗎?
參考以下代碼:
public delegate void treeinvoke();
private void UpdateTreeView()
{
MessageBox.Show(System.Threading.Thread.CurrentThread.Name);
}
private void button1_Click(object sender, System.EventArgs e)
{
System.Threading.Thread.CurrentThread.Name = "UIThread";
treeView1.BeginInvoke(new treeinvoke(UpdateTreeView));
}
看看運(yùn)行結(jié)果,彈出的對(duì)話框中顯示的是 UIThread,這說明 BeginInvoke 所調(diào)用的委托根本就是在 UI 線程中執(zhí)行的。
既然是在 UI 線程中執(zhí)行,又何來“異步執(zhí)行”一說呢?
我們?cè)倏纯聪旅娴拇a:
public delegate void treeinvoke();
private void UpdateTreeView()
{
MessageBox.Show(Thread.CurrentThread.Name);
}
private void button1_Click(object sender, System.EventArgs e)
{
Thread.CurrentThread.Name = "UIThread";
Thread th = new Thread(new ThreadStart(StartThread));
th.Start();
}
private void StartThread()
{
Thread.CurrentThread.Name = "Work Thread";
treeView1.BeginInvoke(new treeinvoke(UpdateTreeView));
}
再看看運(yùn)行結(jié)果,彈出的對(duì)話框中顯示的還是 UIThread,這說明什么?這說明 BeginInvoke 方法所調(diào)用的委托無論如何都是在 UI 線程中執(zhí)行的。
那 BeginInvoke 究竟有什么用呢?
在多線程編程中,我們經(jīng)常要在工作線程中去更新界面顯示,而在多線程中直接調(diào)用界面控件的方法是錯(cuò)誤的做法,具體的原因可以在看完我的這篇之后看看這篇:在多線程中如何調(diào)用Winform,如果你是大牛的話就不要看我這篇了,直接看那篇吧,反正那篇文章我沒怎么看懂。
Invoke 和 BeginInvoke 就是為了解決這個(gè)問題而出現(xiàn)的,使你在多線程中安全的更新界面顯示。
正確的做法是將工作線程中涉及更新界面的代碼封裝為一個(gè)方法,通過 Invoke 或者 BeginInvoke 去調(diào)用,兩者的區(qū)別就是一個(gè)導(dǎo)致工作線程等待,而另外一個(gè)則不會(huì)。
而所謂的“一面響應(yīng)操作,一面添加節(jié)點(diǎn)”永遠(yuǎn)只能是相對(duì)的,使 UI 線程的負(fù)擔(dān)不至于太大而以,因?yàn)榻缑娴恼_更新始終要通過 UI 線程去做,我們要做的事情是在工作線程中包攬大部分的運(yùn)算,而將對(duì)純粹的界面更新放到 UI 線程中去做,這樣也就達(dá)到了減輕 UI 線程負(fù)擔(dān)的目的了。
而在那段更新樹節(jié)點(diǎn)的代碼中,其實(shí)唯一起作用的代碼是:System.Threading.Thread.Sleep(100);,它使 UI 線程有了處理界面消息的機(jī)會(huì),其實(shí) 數(shù)碼幽靈 將問題復(fù)雜化了,只要以下的代碼就可以很好的工作了。
private void button1_Click_(object sender, System.EventArgs e)
{
TreeNode tn;
for(int i=0;i<100000;i++)
{
tn=new TreeNode (i.ToString());
this.treeView1.Nodes[0].Nodes.Add(tn);
if (i%100 == 0) Application.DoEvents();
}
}
相關(guān)文章
C#/VB.NET實(shí)現(xiàn)在Word中插入或刪除腳注
腳注,是可以附在文章頁面的最底端的,對(duì)某些東西加以說明,印在書頁下端的注文。這篇文章將為您展示如何通過C#/VB.NET代碼,以編程方式在Word中插入或刪除腳注,需要的可以參考一下2023-03-03
C#中利用代理實(shí)現(xiàn)觀察者設(shè)計(jì)模式詳解
學(xué)習(xí)模式注重精髓而非模板,本文為了便于說明假定了三方并對(duì)三方功能進(jìn)行了劃分,實(shí)際應(yīng)用并不拘泥于此。如果情況合適將數(shù)據(jù)(文檔)類設(shè)計(jì)為單件模式也是一種很不錯(cuò)的選擇2014-01-01
C# Winform 調(diào)用系統(tǒng)接口操作 INI 配置文件的代碼
封裝了一小段代碼, 調(diào)用系統(tǒng)接口, 操作配置文件. 一般用于 .ini 文件, 或者其它鍵值對(duì)格式的配置文件2011-05-05
關(guān)于C#基礎(chǔ)知識(shí)回顧--反射(二)

