淺述WinForm多線程編程與Control.Invoke的應用

在WinForm開發中,我們通常不希望當窗體上點了某個按鈕執行某個業務的時候,窗體就被卡死了,直到該業務執行完畢后才緩過來。一個最直接的方法便是使用多線程。多線程編程的方式在WinForm開發中必不可少。
本文介紹在WinForm開發中如何使用多線程,以及在線程中如何通過Control.Invoke方法返回窗體主線程執行相關操作。

-. WinForm多線程編程
1. new Thread()

新開一個線程,執行一個方法,沒有參數傳遞:
privatevoid DoWork() {
?Thread t =new Thread(new ThreadStart(this.DoSomething));
?t.Start();
?}

private void DoSomething() {
?MessageBox.Show("thread start");
?}

新開一個線程,執行一個方法,并傳遞參數:
privatevoid DoWork() {
?Thread t =new Thread(new ParameterizedThreadStart(this.DoSomething));
?t.Start("guozhijian");
?}

private void DoSomething(object o) {
?MessageBox.Show(o.ToString());
?}
參數定義為object類型。
2. ThreadPool
眾所周知,新開一個線程代價是很高昂的,如果我們每個操作都新開一個線程,那么太浪費了,于是,下面使用線程池。
無參數傳遞:
privatevoid DoWork(){
?ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething));
?}

private void DoSomething(object o) {
?MessageBox.Show("thread start");
?}
有參數傳遞:
privatevoid DoWork() {
?ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething),"guozhijian");
?}

private void DoSomething(object o) {
?MessageBox.Show(o.ToString());
?}
使用匿名方法更靈活:
privatevoid DoWork() {
string name = "guozhijian";
?ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o){
?MessageBox.Show(name);
?}
));
?}
在匿名代碼段里面可以直接訪問局部變量,不用在關心參數傳遞的問題
二. Invoke
1. this.Invoke
現在,在業務線程里面執行完畢,要改變窗體控件的值了,此時,如果直接通過this得到控件的句柄,然后對它進行操作是會拋異常的,.Net WinForm Application里面是不允許這樣的操作的。這是,可以調用Invoke方法

2.Invoke方法簽名:
object Control.Invoke(Delegate Method)
object Control.Invoke(Delegate Method, params object[] args)

3.使用自定義委托
privatevoid DoWork() {
?WaitCallback wc =new WaitCallback(this.DoSomething);
?ThreadPool.QueueUserWorkItem(wc,"Guozhijian");
?}


private delegate void MyInvokeDelegate(string name);
private void DoSomething(object o) {
this.Invoke(new MyInvokeDelegate(this.ChangeText), o.ToString());
?}


private void ChangeText(string name) {
this.textBox1.Text = name;
?}
哦,太麻煩了,難道我每次都要定義一個委托啊,這樣可不行。

4.使用System.Action:
privatevoid DoWork() {
?WaitCallback wc =new WaitCallback(this.DoSomething);
?ThreadPool.QueueUserWorkItem(wc,"Guozhijian");
?}

private void DoSomething(object o) {
this.Invoke(new Action<string>(this.ChangeText), o.ToString());
?}


private void ChangeText(string name) {
this.textBox1.Text = name;
?}
本例傳遞一個參數,System.Action有很多個重載,可以無參數(非泛型),而最多可以有四個參數,同樣采用匿名方法,不使用泛型形式的System.Action,如下:
privatevoid DoWork() {
?WaitCallback wc =new WaitCallback(this.DoSomething);
?ThreadPool.QueueUserWorkItem(wc,"Guozhijian");
?}

private void DoSomething(object o) {
this.Invoke(new Action(delegate(){
this.textBox1.Text = o.ToString();
?}
));
?}

5.使用System.Func
如果Invoke調用主窗體操作之后,還希望在調用完得到一個返回值:
privatevoid DoWork() {
?WaitCallback wc =new WaitCallback(this.DoSomething);
?ThreadPool.QueueUserWorkItem(wc,"Guozhijian");
?}

private void DoSomething(object o) {
?System.Func<string,int> f = new Func<string, int>(this.GetId);
object result = this.Invoke(f,o.ToString());
?MessageBox.Show(result.ToString());
?}


private int GetId(string name) {
this.textBox1.Text = name;
if (name == "Guozhijian"){
return 999;
?}

else {
return 0;
?}

?}

result的值為 999。
System.Func同樣有很多泛形重載,這里不贅述。

6.關于Invoke的擁有者:Control

本文例中都是用this來引用,這里this替換為窗體任何一個控件的句柄都是OK的,因為Control.Invoke含義是將方法委托給擁有該Control的線程去執行。?

轉載:http://www.cnblogs.com/ghfsusan/archive/2011/12/28/2304310.html

轉載于:https://www.cnblogs.com/aiwz/p/6153924.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/274128.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/274128.shtml
英文地址,請注明出處:http://en.pswp.cn/news/274128.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android 第五課 常用控件的使用方法(TextView、Button、EditView、 ImageView、 ProgressBar、 ProgressDialog等)

總結&#xff1a;見名知意 TextView&#xff1a; Button: EditView: ImageView: ProgressBar: ProgressDialog和AlertDialog有些類似&#xff0c;都可以再界面彈出對話框&#xff0c;都能夠屏蔽其他控件的交互能力&#xff0c;用法也類似。 我們還發現ProgressDialog和AlertDia…

設計 色彩 構圖 創意_我們可以從時尚的創意方向中學到色彩

設計 色彩 構圖 創意The application of fashion as a form of aesthetic expression is a notion familiar to many. Every day, we curate ourselves with inspiration from rising trends, a perception of our personal preferences, and regards to practicality in the c…

Android 第六課 4種基本布局之LinearLayout和Relativelayout

看完控件&#xff0c;緊接著看布局&#xff0c;布局是可以來放置控件&#xff0c;管理控件的。布局里也可以嵌套布局。我們新建項目UILayoutTest項目&#xff0c;活動名和布局名選擇默認。加入活動及其對應的布局已經創建完成。線性布局(LinearLayout)android:layout_gravity屬…

如何在UI設計中制作完美陰影

重點 (Top highlight)Shadows are everywhere in modern UI Designs. They are one of the most essential part of the UI elements right behind the fill, stroke, and cornder radius. &#x1f609;現代UI設計中到處都有陰影。 它們是UI元素中最重要的部分之一&#xff0c…

微軟2013年校園實習生招聘筆試題及答案

原文&#xff1a; http://www.wangkaimin.com/2013/04/07/%e5%be%ae%e8%bd%af2013%e5%b9%b4%e6%a0%a1%e5%9b%ad%e5%ae%9e%e4%b9%a0%e7%94%9f%e6%8b%9b%e8%81%98%e7%ac%94%e8%af%95%e9%a2%98%e5%8f%8a%e7%ad%94%e6%a1%88/#more-195 1. Which of following calling convension(s)…

Android 第七課 4種基本布局之FrameLayout和百分比布局

FrameLayout&#xff08;幀布局&#xff09;&#xff0c;她沒有方便的定位方式&#xff0c;所有的控件都會默認擺放在布局的左上角。 修改activity_main.xml中的代碼&#xff0c;如下&#xff1a; <?xml version"1.0" encoding"utf-8"?> <Frame…

mongodb 群集圖_群集和重疊條形圖

mongodb 群集圖為什么和如何 (Why & How) 1.- Clustered Bar Charts1.- 集群條形圖 AKA: grouped, side-by-side, multiset [bar charts, bar graphs, column charts]AKA &#xff1a;分組&#xff0c;并排&#xff0c;多組[條形圖&#xff0c;條形圖&#xff0c;柱形圖] …

第一次寫python

這是一個在BJDP上學習Coding Kata的時候用到的一個練習&#xff0c;原來打算用Java寫的&#xff0c;但是一想正好是學習的好機會。 就用Python了。第一次&#xff0c;寫的有些復雜。 這個題目是關于購買圖書的打折信息的。 題目來源&#xff1a; http://codingdojo.org/cgi-bin…

Android 第八課 創建自定義控件

常用控件和布局的繼承結構&#xff0c;如下圖&#xff1a; &#xff08;待續。。。。&#xff09; 所有的控件都是直接或間接繼承自View的&#xff0c;所用的所有布局都是直接或間接繼承自ViewGroup的&#xff0c;View是Android中最基本的一種UI組件&#xff0c;它可以在屏幕上…

figma下載_搬到Figma對我意味著什么

figma下載A couple of years ago, amidst the boom of new design and prototyping software, I was pretty reluctant to fight on the Figma/Sketch cold war. I was working on a relatively small design team and, after years helping to design products, well sold on …

解決IE中img.onload失效的方法

解決IE中img.onload失效的方法 - CoffeeCats IT Blog - IT博客http://www.cnitblog.com/CoffeeCat/archive/2008/02/01/39533.htmlFirefox、Google Chrome不存在問題&#xff01;為什么onload沒有被IE調用呢&#xff1f;因為IE會緩存圖片&#xff0c;第2次加載的圖片&#xff0…

Android 第九課 常用控件-------ListView

ListView允許用戶通過手指上下滑動的方式將屏幕外的數據滾動到屏幕內&#xff0c;同時屏幕上原有數據將會滾動出屏幕。 1、ListView簡單用法 如何將ListView將你要顯示的大量內容關聯起來呢&#xff1f;這是個很重要的問題。 1、首先我們必須先將數據提供好&#xff0c;因為你的…

Singleton patterns 單件(創建型模式)

1、模式分類 1.1 從目的來看&#xff1a; ? – 創建型&#xff08;Creational&#xff09;模式&#xff1a;負責對象創建。 ? – 結構型&#xff08;Structural&#xff09;模式&#xff1a;處理類與對象間的組合。 ? – 行為型&#xff08;Behavioral&…

Android 第十一課 SQlite 數據庫存儲

Android 為了讓我們能夠更加方便的管理數據庫&#xff0c;特意提供了一個SQLiteOpenHelper幫助類&#xff0c;通過借助這個類就可以非常簡單的對數據庫進行創建和升級。 SQLiteOpenHelper是一個抽象類&#xff0c;我們要創建一個自己的幫助類去繼承它。SQLiteOpenHelper有兩個抽…

淺析SQL Server 2005中的主動式通知機制

一、引言 在開發多人同時訪問的Web應用程序&#xff08;其實不只這類程序&#xff09;時&#xff0c;開發人員往往會在緩存策略的設計上狠下功夫。這是因為&#xff0c;如果將這種環境下不常變更的數據臨時存放在應用程序服務器或是用戶機器上的話&#xff0c;可以避免頻繁地往…

Android 第十二課 使用LitePal操作數據庫(記得閱讀最后面的注意事項哦)

一、LitePal簡介 1、(新建項目LitePalTest)正式接觸第一個開源庫---LitePalLitePal是一款開源的Android 數據庫框架&#xff0c;它采用了對象關系映射&#xff08;ORM&#xff09;的模式。2、配置LitePal&#xff0c;編輯app/build.gradle文件&#xff0c;在dependencies閉包中…

listview頻繁刷新報錯

在Android編程中使用Adapter時&#xff0c;偶爾會出現如下錯誤&#xff1a;The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI t…

Android 第十三課 SharedPreferences存儲

SharedPreferences是使用鍵值對的方式來存儲數據的。當保存一條數據時&#xff0c;需要給這條數據提供一個對應的鍵&#xff0c;這樣在讀取數據的時候就可以通過這個鍵把相應的值取出來。而且支SharedPreferences還支持多種不同的數據類型存儲&#xff0c;例如&#xff1a;如果…

DSP的Gel作用

轉自&#xff1a;http://blog.csdn.net/azhgul/article/details/6660960最近剛在研究Davinci系&#xff0c;特此MARK下&#xff0c;以資后續學習之用。 DSP的Gel作用 1 GEL文件基本作用 當CCSStudio啟動時&#xff0c;GEL文件加載到PC機的內存中&#xff0c;如果定義了StartUp(…

解決關于登錄校園網顯示不在IP段的問題方案(要看注意事項哦!)

有時&#xff0c;登錄校園網&#xff0c;賬號和密碼都顯示正確&#xff0c;但是卻顯示出“賬號只能在指定IP段登錄”的問題。 那我們就提供了一個解決方案&#xff1a; 使用WinR,并在輸入框&#xff0c;輸入cmd命令&#xff1a;&#xff08;如下&#xff09;接著輸入&#xff1…