.Net Winform開發(fā)筆記(一)
更新時(shí)間:2013年01月14日 16:13:52 作者:
理解“Windows 窗體應(yīng)用程序”項(xiàng)目中Program.cs文件中的main方法與傳統(tǒng)C++Console控制臺(tái)程序中的main方法的區(qū)別等等,感興趣的朋友可以了解下
1. 理解“Windows 窗體應(yīng)用程序”項(xiàng)目中Program.cs文件中的main方法與傳統(tǒng)C++Console控制臺(tái)程序中的main方法的區(qū)別。從程序運(yùn)行層次上講,兩者無(wú)區(qū)別,都是程序的入口點(diǎn),屬于進(jìn)程中的第一個(gè)線程。前者隱藏了UI應(yīng)用程序必需的消息循環(huán),后者沒有。
2. 每個(gè)Windows桌面應(yīng)用程序都必須包含至少一個(gè)UI線程,所謂UI線程,就是可以響應(yīng)Windows消息的線程。通常情況下,除非特別需要,一個(gè)Windows桌面應(yīng)用程序只包含一個(gè)UI線程。
3. UI線程本質(zhì)上跟普通線程一樣,一般為程序的入口線程,比如Program.cs文件中的main方法,就是UI線程,而Application.Run()方法中封裝了消息循環(huán)。如果沒有Application.Run()方法,那么它跟其他線程一模一樣。之所以叫做UI線程,是因?yàn)樗邪粋€(gè)類似
While(GetMessage(…))//取Windows消息
{
//處理windows消息,調(diào)用開發(fā)者編寫的回調(diào)方法,如事件處理程序 等。
}
的循環(huán)。
4. 有關(guān)Windows消息機(jī)制等內(nèi)容,請(qǐng)上網(wǎng)Google或者百度。
5. UI線程主要負(fù)責(zé)界面的實(shí)時(shí)更新,所以開發(fā)人員編寫代碼時(shí),請(qǐng)遵守以下規(guī)律:
1) 不要在控件的事件處理程序中編寫(或者調(diào)用)耗時(shí)的代碼塊;
2) 不要在控件的事件處理程序中調(diào)用阻塞方法;
6. 明白程序設(shè)計(jì)中的 委托、事件、事件處理程序的區(qū)別
1) Publicdelegate void KeyPressEventHandler(KeyPressEventArgse);
2) Public eventKeyPressEventHandler KeyPress;
3) Public void Textbox1_KeyPress(objectsender,KeyPressEventArgs e)
{
//….
}
其中:
1為委托 2為事件 3為事件處理程序
7. 所有的事件處理程序都是在UI線程中調(diào)用,又因?yàn)閁I線程負(fù)責(zé)更新界面,所以UI線程始終必須保持順暢(表現(xiàn)為3中的while循環(huán)體不能耗時(shí)太長(zhǎng)),即不能出現(xiàn)長(zhǎng)時(shí)間執(zhí) 行一個(gè)方法不返回的情況。所以,請(qǐng)遵守5中的規(guī)律。
8. 同一個(gè)方法,可以運(yùn)行在多個(gè)線程之中,方法跟線程沒有一對(duì)一的原則
Private void thread_pro() //
{
}
1) privatebutton1_click(object sender,EventArgs e)
{
thread_pro(); //thread_pro運(yùn)行在UI線程中
}
2)private button1_click(object sender,EventArgs e)
{
Thread t = new Thread(newThreadStart(thread_pro));
Thread t1 = new Thread(new ThreadStart(thread_pro));
Thread t2 = newThread(new ThreadStart(thread_pro));
t.start(); //thread_pro運(yùn)行在t線程中
t1.start(); //thread_pro運(yùn)行在t1線程中
t.2.start(); //thread_pro運(yùn)行在t2線程中
}
3) 還可以通過Control.Invoke() 或者BenginInvoke方法將方法投遞到創(chuàng)建該控件的線程中執(zhí)行。
以上所有情況,請(qǐng)注意線程共享數(shù)據(jù)。
9. 多線程編程中,請(qǐng)注意“線程安全”問題,對(duì)于一些具備“非原子”操作的對(duì)象,必須采取措施避免發(fā)生錯(cuò)誤。
UI控件(Button、datagridview等等)、集合(List、ArrayList)等屬于此類對(duì)象,控件任何時(shí)間都不能多線程訪問。
10. 堅(jiān)決杜絕跨線程訪問UI控件,原因見9??缇€程訪問控件的方法見8中的3)。
11. 除了.Net Winform中的事件處理程序是在UI線程中調(diào)用以外,其它的回調(diào)方法幾乎所有都不會(huì)在UI線程中執(zhí)行,所以,開發(fā)人員在編寫回調(diào)方法時(shí),請(qǐng)遵守第9,10兩大規(guī)律。
12. 明白什么叫回調(diào)方法?;卣{(diào)方法一般由開發(fā)者編寫,但不由開發(fā)者調(diào)用,由系統(tǒng)(或者說框架)調(diào)用。在Windows桌面應(yīng)用程序開發(fā)過程中,控件的事件處理程序都屬于回調(diào)方法,回調(diào)方法一般用在“觀察者”設(shè)計(jì)模式中,當(dāng)事件的激發(fā)者激發(fā)一個(gè)事件時(shí),它就會(huì)調(diào)用回調(diào)方法。控件的所有事件都屬于此類。
另外一種常見為,異步執(zhí)行某個(gè)操作,譬如,socket.BeginAccept()中的AsyncCallBack類型參數(shù)。
在框架橫行的時(shí)代,一般開發(fā)者編寫的代碼都屬于回調(diào)代碼。因?yàn)槌绦虻闹饕Y(jié)構(gòu)都由先輩們?cè)诳蚣苤屑珊昧?。開發(fā)者們只需要像填空一樣完善空缺的部分。
13. 阻塞方法指,由于方法體內(nèi)包含耗時(shí)較長(zhǎng)的操作,所以方法不能及時(shí)返回。
所謂“及時(shí)”與“非及時(shí)”沒有絕對(duì)界限,示例如下:
int func1() //及時(shí)返回
{
Int index = 0;
For(int i=0;i<100;i++)
{
Index ++;
}
Return index;
}
Int func2() //非及時(shí)返回
{
Int index = 0;
For(int i=0;i<1000;i++)
{
For(int j=0;j<1000;++j)
{
Index ++;
}
}
Return index;
}
上述func1相對(duì)而言,屬于非阻塞方法,func2屬于阻塞方法。
14. Windows窗體應(yīng)用程序不會(huì)直接跟鍵盤、鼠標(biāo)等硬件設(shè)備交互,它只與Windows消息有直接交互。雖然表面上鼠標(biāo)鍵盤等硬件設(shè)備是操作在窗體之上的,但實(shí)質(zhì)上,你 編寫的桌面應(yīng)用程序是不會(huì)理解這些硬件設(shè)備的一舉一動(dòng)。他們是通過操作系統(tǒng)(驅(qū)動(dòng)程序)進(jìn)行橋接的,操作系統(tǒng)先將硬件設(shè)備的一舉一動(dòng)翻譯成windows消息(一種數(shù)據(jù)結(jié)構(gòu),程序可以理解),然后供程序理解,作出相應(yīng)的反應(yīng)。
15. 所謂“阻塞調(diào)用線程”,是指在某一個(gè)線程中調(diào)用了阻塞方法,從而使該線程不能及時(shí)執(zhí)行以后的代碼。
Void func()
{
Int index=0;
For(int i=0;i<10000;++i)
{
For(int j=0;j<10000;++j)
{
I ndex++;
}
}
}
Thread t = newThread(new ThreadStart(func));
t.Start(); //線程t中調(diào)用了阻塞方法func,因此線程t會(huì)被阻塞
在介紹func方法時(shí),可以這樣描述:該方法會(huì)阻塞調(diào)用線程。
16. 同一個(gè)方法可以被多個(gè)線程調(diào)用,既可被UI線程調(diào)用,也可被非UI線程調(diào)用,那么在方法體內(nèi)怎么編寫訪問UI控件(UI元素)的代碼呢?(跨線程訪問UI控件會(huì)引發(fā)異常)
Void func()
{
Textbox1.Text=”測(cè)試”;
PictureBox1.Image = Image.FromFile(“a.jpg”);
}
1)以上func方法可能運(yùn)行在UI線程中,如下:
Private voidbutton1_Click(object sender,EventArgs e)
{
func(); //調(diào)用func方法
}
2)有如下,func方法可能運(yùn)行在其他非UI線程中
Private void button1_Click(object sender,EventArgs e)
{
Thread t = new Thread(newThreadStart(func));
t.Start(); //func訪問運(yùn)行在t線程中
}
在2)中,可能引發(fā)異常。
以上問題的解決方案為:
修改func代碼為:
Func()
{
If(this.InvokeRequired)
{
This.BeginInvoke((Action)delegate(){func()});
}
Else
{
Textbox1.Text=”測(cè)試”;
PictureBox1.Image = Image.FromFile(“a.jpg”);
}
}
有關(guān)BeginInvoke或者Invoke方法的使用,請(qǐng)上網(wǎng)Google或者百度。
17. 有關(guān)“跨線程訪問UI控件可能引發(fā)異常”的原因,跟多線程訪問集合可能出現(xiàn)錯(cuò)誤的原因基本相似。下面列舉一段代碼說明情況
ClassMyControl
{
Object root;
Public Draw()
{
GetRoot(root);
// 一系列操作…
ReleaseRoot(root);
}
Public OtherDraw()
{
GetRoot(root);
// 一系列操作 …
ReleaseRoot(root);
}
}
其中root變量同時(shí)只能被占用一次,GetRoot()獲取root的訪問權(quán),如果root已經(jīng)被占用,則拋出異常。ReleaseRoot()釋放root占用。
當(dāng)在一個(gè)線程中(比如UI線程中)訪問MyControl類對(duì)象A,調(diào)用A.Draw()方法,執(zhí)行到GetRoot(root)方法后,該線程失去控制權(quán),暫停運(yùn)行一下的代碼,即此時(shí)root已被占用。而另一線程中如果也要訪問同一對(duì)象A的Draw()方法,那么就會(huì)引發(fā)異常。
18.在.Net Winform應(yīng)用程序中,程序與用戶的交互主要包含兩個(gè)方面,一是用戶用鼠標(biāo)、鍵盤燈硬件設(shè)備進(jìn)行操作,程序響應(yīng)操作,然后進(jìn)行反饋(比如更新界面、刷新數(shù)據(jù)等),二是不需要用戶用鼠標(biāo)等硬件設(shè)備進(jìn)行操作,程序自己自動(dòng)進(jìn)行反饋(比如QQ彈出新聞窗體、360彈窗等)。
第一種情況是我們所熟知的,比如用戶用鼠標(biāo)點(diǎn)擊按鈕(button1),程序則彈出一個(gè)MessageBox,我們?cè)诔绦蛑惺沁@樣子寫的:事件處理程序如下
Private voidbutton1_Click(object sender,EventArgs e)
{
MessageBox.Show(“彈出對(duì)話框,或者其他操作”);
}
再來(lái)理一下這個(gè)過程,首先用戶拿起鼠標(biāo)點(diǎn)擊button1,操作系統(tǒng)(鼠標(biāo)驅(qū)動(dòng))會(huì)捕獲這個(gè)事件,經(jīng)過分析,操作系統(tǒng)得知用戶點(diǎn)擊的是哪個(gè)窗體(按鈕)、點(diǎn)擊的位置(坐標(biāo)),點(diǎn)擊類型(左鍵還是右鍵或者其他),以及其他信息,之后,將這些信息封裝成一個(gè)類型(即windows消息)發(fā)送給創(chuàng)建該窗體(控件)的線程中的消息隊(duì)列,之后,操作系統(tǒng)(鼠標(biāo)驅(qū)動(dòng))就不在負(fù)責(zé)了。接著,UI線程從線程消息隊(duì)列中獲取該消息(注意:這個(gè)過程是一直存在的),分析消息,調(diào)用開發(fā)人員編寫的一些回調(diào)方法,如button1_Click()方法,從而到達(dá)相應(yīng)鼠標(biāo)鍵盤操作的目的。從上面分析過程來(lái)看,再一次說明,程序是不會(huì)直接跟鼠標(biāo)等硬件設(shè)備交互的,與它直接交互的只有Windows消息,而這個(gè)過程需要Windows操作系統(tǒng)起著重要作用。
第二種情況一般用在多線程編程中,當(dāng)程序有耗時(shí)操作、或者需要一直監(jiān)聽等情況的時(shí)候,是不能放在UI線程之中的,這時(shí)候就需要另外開辟線程,在另外的線程中處理。這種情況中,另外開辟的線程有時(shí)候需要反饋跟用戶一些信息,即更新UI界面或者彈出一個(gè)窗體等,這就涉及到跨線程訪問UI元素的問題了,詳見5和
19.以上代碼部分均為現(xiàn)寫的,可能出現(xiàn)拼寫錯(cuò)誤,包涵!
另外,請(qǐng)配合筆記(二)中的“DOT NETWinform應(yīng)用程序運(yùn)行結(jié)構(gòu)圖”閱讀。
2. 每個(gè)Windows桌面應(yīng)用程序都必須包含至少一個(gè)UI線程,所謂UI線程,就是可以響應(yīng)Windows消息的線程。通常情況下,除非特別需要,一個(gè)Windows桌面應(yīng)用程序只包含一個(gè)UI線程。
3. UI線程本質(zhì)上跟普通線程一樣,一般為程序的入口線程,比如Program.cs文件中的main方法,就是UI線程,而Application.Run()方法中封裝了消息循環(huán)。如果沒有Application.Run()方法,那么它跟其他線程一模一樣。之所以叫做UI線程,是因?yàn)樗邪粋€(gè)類似
復(fù)制代碼 代碼如下:
While(GetMessage(…))//取Windows消息
{
//處理windows消息,調(diào)用開發(fā)者編寫的回調(diào)方法,如事件處理程序 等。
}
的循環(huán)。
4. 有關(guān)Windows消息機(jī)制等內(nèi)容,請(qǐng)上網(wǎng)Google或者百度。
5. UI線程主要負(fù)責(zé)界面的實(shí)時(shí)更新,所以開發(fā)人員編寫代碼時(shí),請(qǐng)遵守以下規(guī)律:
1) 不要在控件的事件處理程序中編寫(或者調(diào)用)耗時(shí)的代碼塊;
2) 不要在控件的事件處理程序中調(diào)用阻塞方法;
6. 明白程序設(shè)計(jì)中的 委托、事件、事件處理程序的區(qū)別
復(fù)制代碼 代碼如下:
1) Publicdelegate void KeyPressEventHandler(KeyPressEventArgse);
2) Public eventKeyPressEventHandler KeyPress;
3) Public void Textbox1_KeyPress(objectsender,KeyPressEventArgs e)
{
//….
}
其中:
1為委托 2為事件 3為事件處理程序
7. 所有的事件處理程序都是在UI線程中調(diào)用,又因?yàn)閁I線程負(fù)責(zé)更新界面,所以UI線程始終必須保持順暢(表現(xiàn)為3中的while循環(huán)體不能耗時(shí)太長(zhǎng)),即不能出現(xiàn)長(zhǎng)時(shí)間執(zhí) 行一個(gè)方法不返回的情況。所以,請(qǐng)遵守5中的規(guī)律。
8. 同一個(gè)方法,可以運(yùn)行在多個(gè)線程之中,方法跟線程沒有一對(duì)一的原則
復(fù)制代碼 代碼如下:
Private void thread_pro() //
{
}
1) privatebutton1_click(object sender,EventArgs e)
{
thread_pro(); //thread_pro運(yùn)行在UI線程中
}
2)private button1_click(object sender,EventArgs e)
{
Thread t = new Thread(newThreadStart(thread_pro));
Thread t1 = new Thread(new ThreadStart(thread_pro));
Thread t2 = newThread(new ThreadStart(thread_pro));
t.start(); //thread_pro運(yùn)行在t線程中
t1.start(); //thread_pro運(yùn)行在t1線程中
t.2.start(); //thread_pro運(yùn)行在t2線程中
}
3) 還可以通過Control.Invoke() 或者BenginInvoke方法將方法投遞到創(chuàng)建該控件的線程中執(zhí)行。
以上所有情況,請(qǐng)注意線程共享數(shù)據(jù)。
9. 多線程編程中,請(qǐng)注意“線程安全”問題,對(duì)于一些具備“非原子”操作的對(duì)象,必須采取措施避免發(fā)生錯(cuò)誤。
UI控件(Button、datagridview等等)、集合(List、ArrayList)等屬于此類對(duì)象,控件任何時(shí)間都不能多線程訪問。
10. 堅(jiān)決杜絕跨線程訪問UI控件,原因見9??缇€程訪問控件的方法見8中的3)。
11. 除了.Net Winform中的事件處理程序是在UI線程中調(diào)用以外,其它的回調(diào)方法幾乎所有都不會(huì)在UI線程中執(zhí)行,所以,開發(fā)人員在編寫回調(diào)方法時(shí),請(qǐng)遵守第9,10兩大規(guī)律。
12. 明白什么叫回調(diào)方法?;卣{(diào)方法一般由開發(fā)者編寫,但不由開發(fā)者調(diào)用,由系統(tǒng)(或者說框架)調(diào)用。在Windows桌面應(yīng)用程序開發(fā)過程中,控件的事件處理程序都屬于回調(diào)方法,回調(diào)方法一般用在“觀察者”設(shè)計(jì)模式中,當(dāng)事件的激發(fā)者激發(fā)一個(gè)事件時(shí),它就會(huì)調(diào)用回調(diào)方法。控件的所有事件都屬于此類。
另外一種常見為,異步執(zhí)行某個(gè)操作,譬如,socket.BeginAccept()中的AsyncCallBack類型參數(shù)。
在框架橫行的時(shí)代,一般開發(fā)者編寫的代碼都屬于回調(diào)代碼。因?yàn)槌绦虻闹饕Y(jié)構(gòu)都由先輩們?cè)诳蚣苤屑珊昧?。開發(fā)者們只需要像填空一樣完善空缺的部分。
13. 阻塞方法指,由于方法體內(nèi)包含耗時(shí)較長(zhǎng)的操作,所以方法不能及時(shí)返回。
所謂“及時(shí)”與“非及時(shí)”沒有絕對(duì)界限,示例如下:
復(fù)制代碼 代碼如下:
int func1() //及時(shí)返回
{
Int index = 0;
For(int i=0;i<100;i++)
{
Index ++;
}
Return index;
}
Int func2() //非及時(shí)返回
{
Int index = 0;
For(int i=0;i<1000;i++)
{
For(int j=0;j<1000;++j)
{
Index ++;
}
}
Return index;
}
上述func1相對(duì)而言,屬于非阻塞方法,func2屬于阻塞方法。
14. Windows窗體應(yīng)用程序不會(huì)直接跟鍵盤、鼠標(biāo)等硬件設(shè)備交互,它只與Windows消息有直接交互。雖然表面上鼠標(biāo)鍵盤等硬件設(shè)備是操作在窗體之上的,但實(shí)質(zhì)上,你 編寫的桌面應(yīng)用程序是不會(huì)理解這些硬件設(shè)備的一舉一動(dòng)。他們是通過操作系統(tǒng)(驅(qū)動(dòng)程序)進(jìn)行橋接的,操作系統(tǒng)先將硬件設(shè)備的一舉一動(dòng)翻譯成windows消息(一種數(shù)據(jù)結(jié)構(gòu),程序可以理解),然后供程序理解,作出相應(yīng)的反應(yīng)。
15. 所謂“阻塞調(diào)用線程”,是指在某一個(gè)線程中調(diào)用了阻塞方法,從而使該線程不能及時(shí)執(zhí)行以后的代碼。
復(fù)制代碼 代碼如下:
Void func()
{
Int index=0;
For(int i=0;i<10000;++i)
{
For(int j=0;j<10000;++j)
{
I ndex++;
}
}
}
Thread t = newThread(new ThreadStart(func));
t.Start(); //線程t中調(diào)用了阻塞方法func,因此線程t會(huì)被阻塞
在介紹func方法時(shí),可以這樣描述:該方法會(huì)阻塞調(diào)用線程。
16. 同一個(gè)方法可以被多個(gè)線程調(diào)用,既可被UI線程調(diào)用,也可被非UI線程調(diào)用,那么在方法體內(nèi)怎么編寫訪問UI控件(UI元素)的代碼呢?(跨線程訪問UI控件會(huì)引發(fā)異常)
復(fù)制代碼 代碼如下:
Void func()
{
Textbox1.Text=”測(cè)試”;
PictureBox1.Image = Image.FromFile(“a.jpg”);
}
1)以上func方法可能運(yùn)行在UI線程中,如下:
復(fù)制代碼 代碼如下:
Private voidbutton1_Click(object sender,EventArgs e)
{
func(); //調(diào)用func方法
}
2)有如下,func方法可能運(yùn)行在其他非UI線程中
復(fù)制代碼 代碼如下:
Private void button1_Click(object sender,EventArgs e)
{
Thread t = new Thread(newThreadStart(func));
t.Start(); //func訪問運(yùn)行在t線程中
}
在2)中,可能引發(fā)異常。
以上問題的解決方案為:
修改func代碼為:
復(fù)制代碼 代碼如下:
Func()
{
If(this.InvokeRequired)
{
This.BeginInvoke((Action)delegate(){func()});
}
Else
{
Textbox1.Text=”測(cè)試”;
PictureBox1.Image = Image.FromFile(“a.jpg”);
}
}
有關(guān)BeginInvoke或者Invoke方法的使用,請(qǐng)上網(wǎng)Google或者百度。
17. 有關(guān)“跨線程訪問UI控件可能引發(fā)異常”的原因,跟多線程訪問集合可能出現(xiàn)錯(cuò)誤的原因基本相似。下面列舉一段代碼說明情況
復(fù)制代碼 代碼如下:
ClassMyControl
{
Object root;
Public Draw()
{
GetRoot(root);
// 一系列操作…
ReleaseRoot(root);
}
Public OtherDraw()
{
GetRoot(root);
// 一系列操作 …
ReleaseRoot(root);
}
}
其中root變量同時(shí)只能被占用一次,GetRoot()獲取root的訪問權(quán),如果root已經(jīng)被占用,則拋出異常。ReleaseRoot()釋放root占用。
當(dāng)在一個(gè)線程中(比如UI線程中)訪問MyControl類對(duì)象A,調(diào)用A.Draw()方法,執(zhí)行到GetRoot(root)方法后,該線程失去控制權(quán),暫停運(yùn)行一下的代碼,即此時(shí)root已被占用。而另一線程中如果也要訪問同一對(duì)象A的Draw()方法,那么就會(huì)引發(fā)異常。
18.在.Net Winform應(yīng)用程序中,程序與用戶的交互主要包含兩個(gè)方面,一是用戶用鼠標(biāo)、鍵盤燈硬件設(shè)備進(jìn)行操作,程序響應(yīng)操作,然后進(jìn)行反饋(比如更新界面、刷新數(shù)據(jù)等),二是不需要用戶用鼠標(biāo)等硬件設(shè)備進(jìn)行操作,程序自己自動(dòng)進(jìn)行反饋(比如QQ彈出新聞窗體、360彈窗等)。
第一種情況是我們所熟知的,比如用戶用鼠標(biāo)點(diǎn)擊按鈕(button1),程序則彈出一個(gè)MessageBox,我們?cè)诔绦蛑惺沁@樣子寫的:事件處理程序如下
復(fù)制代碼 代碼如下:
Private voidbutton1_Click(object sender,EventArgs e)
{
MessageBox.Show(“彈出對(duì)話框,或者其他操作”);
}
再來(lái)理一下這個(gè)過程,首先用戶拿起鼠標(biāo)點(diǎn)擊button1,操作系統(tǒng)(鼠標(biāo)驅(qū)動(dòng))會(huì)捕獲這個(gè)事件,經(jīng)過分析,操作系統(tǒng)得知用戶點(diǎn)擊的是哪個(gè)窗體(按鈕)、點(diǎn)擊的位置(坐標(biāo)),點(diǎn)擊類型(左鍵還是右鍵或者其他),以及其他信息,之后,將這些信息封裝成一個(gè)類型(即windows消息)發(fā)送給創(chuàng)建該窗體(控件)的線程中的消息隊(duì)列,之后,操作系統(tǒng)(鼠標(biāo)驅(qū)動(dòng))就不在負(fù)責(zé)了。接著,UI線程從線程消息隊(duì)列中獲取該消息(注意:這個(gè)過程是一直存在的),分析消息,調(diào)用開發(fā)人員編寫的一些回調(diào)方法,如button1_Click()方法,從而到達(dá)相應(yīng)鼠標(biāo)鍵盤操作的目的。從上面分析過程來(lái)看,再一次說明,程序是不會(huì)直接跟鼠標(biāo)等硬件設(shè)備交互的,與它直接交互的只有Windows消息,而這個(gè)過程需要Windows操作系統(tǒng)起著重要作用。
第二種情況一般用在多線程編程中,當(dāng)程序有耗時(shí)操作、或者需要一直監(jiān)聽等情況的時(shí)候,是不能放在UI線程之中的,這時(shí)候就需要另外開辟線程,在另外的線程中處理。這種情況中,另外開辟的線程有時(shí)候需要反饋跟用戶一些信息,即更新UI界面或者彈出一個(gè)窗體等,這就涉及到跨線程訪問UI元素的問題了,詳見5和
19.以上代碼部分均為現(xiàn)寫的,可能出現(xiàn)拼寫錯(cuò)誤,包涵!
另外,請(qǐng)配合筆記(二)中的“DOT NETWinform應(yīng)用程序運(yùn)行結(jié)構(gòu)圖”閱讀。
您可能感興趣的文章:
- .Net中導(dǎo)出數(shù)據(jù)到Excel(asp.net和winform程序中)
- ASP.NET也像WinForm程序一樣運(yùn)行的實(shí)現(xiàn)方法
- 在WinForm和WPF中使用GMap.Net地圖插件簡(jiǎn)單教程
- 關(guān)于C#.net winform程序驗(yàn)證moss的集成身份認(rèn)證實(shí)例
- .Net WInform開發(fā)筆記(五)關(guān)于事件Event
- .Net Winform開發(fā)筆記(四)透過現(xiàn)象看本質(zhì)
- .Net WInform開發(fā)筆記(三)談?wù)勛灾瓶丶?自定義控件)
- .Net WInform開發(fā)筆記(二)Winform程序運(yùn)行結(jié)構(gòu)圖及TCP協(xié)議在Winform中的應(yīng)用
- Winform實(shí)現(xiàn)調(diào)用asp.net數(shù)據(jù)接口實(shí)例
相關(guān)文章
C#中結(jié)構(gòu)體和字節(jié)數(shù)組轉(zhuǎn)換實(shí)現(xiàn)
這篇文章主要介紹了C#中結(jié)構(gòu)體和字節(jié)數(shù)組轉(zhuǎn)換實(shí)現(xiàn),本文直接給出了字節(jié)數(shù)組與結(jié)構(gòu)體的轉(zhuǎn)換代碼,代碼中包含詳細(xì)注釋,需要的朋友可以參考下2015-06-06如何使用Dapper處理多個(gè)結(jié)果集與多重映射實(shí)例教程
Dapper類是一個(gè)開源的數(shù)據(jù)庫(kù)操作類,下面這篇文章主要給大家介紹了關(guān)于如何使用Dapper處理多個(gè)結(jié)果集與多重映射的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-09-09那些年,我還在學(xué)習(xí)C# 學(xué)習(xí)筆記續(xù)
那些年學(xué)習(xí)C#,就是對(duì)C#相關(guān)的一些知識(shí)有一個(gè)了解,等到要用時(shí)才不會(huì)找不到方向,比如說擴(kuò)展方法,開始時(shí)怎么覺得沒有用,后來(lái)了解到asp.net MVC,它可以用來(lái)擴(kuò)展Html類,比如做一個(gè)分頁(yè)的方法;所以對(duì)一門語(yǔ)言了解寬一些是沒有壞處的2012-03-03WinForm中KeyDown,KeyPress和KeyUp的順序與區(qū)別解析
這篇文章主要介紹了WinForm中KeyDown,KeyPress和KeyUp的順序與區(qū)別解析,對(duì)C#初學(xué)者來(lái)說很有學(xué)習(xí)借鑒價(jià)值,需要的朋友可以參考下2014-08-08Unity接入百度AI實(shí)現(xiàn)貨幣識(shí)別
本文主要介紹了在Unity中接入百度AI,從而實(shí)現(xiàn)貨幣識(shí)別,可以返回貨幣的名稱、代碼、面值、年份信息等,感興趣的可以跟隨小編學(xué)習(xí)一下2022-01-01C#?使用PrintDocument類打印標(biāo)簽的方法
本文介紹打印機(jī)初步配置,以及實(shí)現(xiàn)方法,標(biāo)簽主要展示資產(chǎn)基本信息以及二維碼,對(duì)C#?使用PrintDocument類打印標(biāo)簽的詳細(xì)過程感興趣的朋友一起看看吧2022-04-04DevExpress實(shí)現(xiàn)GridControl根據(jù)列選中一行
這篇文章主要介紹了DevExpress實(shí)現(xiàn)GridControl根據(jù)列選中一行,比較實(shí)用的功能,需要的朋友可以參考下2014-08-08