国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

C#多線程與UI響應(yīng)

2019-11-17 04:08:32
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
在使用C#進(jìn)行應(yīng)用程序設(shè)計(jì)時(shí),經(jīng)常會(huì)采用多線程的方式進(jìn)行一些后臺(tái)任務(wù)的工作。對(duì)于不同的應(yīng)用場(chǎng)景,使用的策略也不盡相同。









1.      后臺(tái)循環(huán)任務(wù),少量UI更新:例如批量上傳文件,并提供進(jìn)度。這種情況使用BackgroundWorker組件是非常好的選擇。









2.      耗時(shí)的后臺(tái)任務(wù):這里的耗時(shí)任務(wù)是指一個(gè)時(shí)間較長(zhǎng)的任務(wù),并且不能精確獲取進(jìn)度,如:調(diào)用一個(gè)遠(yuǎn)程WebService接口。這種情況可以開(kāi)兩個(gè)線程,一個(gè)工作,一個(gè)更新UI(不能提供進(jìn)度,只能顯示動(dòng)畫表示系統(tǒng)在運(yùn)行中)。









3.      耗時(shí)的UI任務(wù):當(dāng)工作壓力集中在UI響應(yīng)上時(shí),可以在工作者線程中增加延時(shí),從而讓UI線程獲得響應(yīng)時(shí)間。整個(gè)工作的總體時(shí)間會(huì)增加,但用戶響應(yīng)效果會(huì)好很多。



















二. 后臺(tái)的循環(huán)任務(wù),少量UI更新








這種情況使用BackgroundWorker組件是最好的選擇。(詳見(jiàn)附一)



















三. 后臺(tái)耗時(shí)任務(wù)








在后臺(tái)執(zhí)行一個(gè)不可分解的耗時(shí)任務(wù),需要進(jìn)行界面更新,以便讓客戶看上去程序有所響應(yīng)。這種情況下,UI線程一般也不知道工作線程何時(shí)結(jié)束,所以一般執(zhí)行循環(huán)任務(wù),當(dāng)工作線程結(jié)束后,關(guān)閉UI線程就可以了。









Thread uithread = null;









PRivate void btnStart_Click(object sender, EventArgs e)




{

    uithread = new Thread(new ThreadStart(this.UpdateProgressThread));

    uithread.Start();

    Thread workthread = new Thread(new ThreadStart(this.DoSomething));

    workthread.Start();

}






private void DoSomething()




{

    Thread.Sleep(5000);

     uithread.Abort();

     MessageBox.Show("work end");

}






private void UpdateProgressThread()




{

    for (int i = 0; i < 10000; i++)

    {

        Thread.Sleep(100);  

        this.Invoke(new Action<int>(this.UpdateProgress), i);

    }

}






private void UpdateProgress(int v)




{           

    this.progressBar1.Value = v;






}



















這里只要注意一點(diǎn):線程調(diào)用的方法都不能訪問(wèn)用戶控件,必須通過(guò)委托調(diào)用Form的方法來(lái)實(shí)現(xiàn)界面更新。



















四. 耗時(shí)的UI任務(wù)








當(dāng)整個(gè)工作壓力集中在UI響應(yīng)上時(shí),可以在工作者線程中增加延時(shí),從而讓UI線程獲得響應(yīng)時(shí)間。整個(gè)工作的總體時(shí)間會(huì)增加,但用戶響應(yīng)效果會(huì)好很多。









private void FormInitForm_Load(object sender, EventArgs e)




{

    this.listView1.Items.Clear();

    Thread workthread = new Thread(new ThreadStart(this.DoSomething));

    workthread.Start();

}






private void DoSomething()




{

    for (int i = 0; i < 30; i++)

    {

        this.Invoke(new Action<int>(this.LoadPicture), i);

        Thread.Sleep(100);

    }

}






private void LoadPicture(int i)




{

    string text = string.Format("Item{0}", i);






    ListViewItem lvi = new ListViewItem(text, 0);




    this.listView1.Items.Add(lvi);

    Thread.Sleep(200);//模擬耗時(shí)UI任務(wù),非循環(huán),不可分解

}
















五. 補(bǔ)充








1.        Invoke 和 BeginInvoke









在多線程編程中,我們經(jīng)常要在工作線程中去更新界面顯示,而在多線程中直接調(diào)用界面控件的方法是錯(cuò)誤的做法,正確的做法是將工作線程中涉及更新界面的代碼封裝為一個(gè)方法,通過(guò) Invoke 或者 BeginInvoke 去調(diào)用,兩者的區(qū)別就是一個(gè)導(dǎo)致工作線程等待,而另外一個(gè)則不會(huì)。









而所謂的“一面響應(yīng)操作,一面添加節(jié)點(diǎn)”永遠(yuǎn)只能是相對(duì)的,使 UI 線程的負(fù)擔(dān)不至于太大而以,因?yàn)榻缑娴恼_更新始終要通過(guò) UI 線程去做,我們要做的事情是在工作線程中包攬大部分的運(yùn)算,而將對(duì)純粹的界面更新放到 UI 線程中去做,這樣也就達(dá)到了減輕 UI 線程負(fù)擔(dān)的目的了。



















2.        application.DoEvent









在耗時(shí)的循環(huán)的UI更新的方法中,插入Application.DoEvent,會(huì)使界面獲得響應(yīng),Application.DoEvent會(huì)調(diào)用消息處理程序。









private void button2_Click(object sender, EventArgs e)




{

    for (int i = 0; i < 30; i++)

    {

        string text = string.Format("Item{0}", i);






        ListViewItem lvi = new ListViewItem(text, 0);




        this.listView1.Items.Add(lvi);

        Thread.Sleep(200);






        for (int j = 0; j < 10; j++)




        {

            Thread.Sleep(10);

            Application.DoEvents();

        }

    }            

}






3.        Lock









lock(object)




{

}






等價(jià)與









try




{

    Monitor.Enter(object);

}

finally

{

    Monitor.Exit(object)

}
















附一:









BackgroundWorker組件使用說(shuō)明









一.            概述









BackgroundWorker是·NET 2.0提供的一個(gè)多線程組件,在應(yīng)用程序中使用,可以非常簡(jiǎn)單方便地實(shí)現(xiàn)UI控件通信,并自動(dòng)處理多線程沖突問(wèn)題。



















二.            基本屬性









1.      WorkerReportsProgress ,bool:是否允許報(bào)告進(jìn)度;









2.      WorkerSupportsCancellation,bool:是否允許取消線程。









3.      CancellationPending,bool,get:讀取用戶是否取消該線程。



















三.            基本事件









1.      DoWork:工作者線程









2.      RunWorkerCompleted :線程進(jìn)度報(bào)告









3.      ProgressChanged:線程結(jié)束報(bào)告



















四.            基本方法









1.      RunWorkerAsync() :?jiǎn)?dòng)工作者線程;









2.      CancelAsync():取消工作者線程;









3.      ReportProgress(int);   報(bào)告進(jìn)度











五.            代碼









//啟動(dòng)




private void btnStart_Click(object sender, EventArgs e)

{

    this.btnStart.Enabled = false;

    this.btnStop.Enabled = true;

    this.backgroundWorker.RunWorkerAsync();

}






//通知線程停止




private void btnStop_Click(object sender, EventArgs e)

{

    this.backgroundWorker.CancelAsync();

}






//工作者線程




private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)

{

    for (int i = 0; i < 150; i++)

    {

        if (backgroundWorker.CancellationPending)   //查看用戶是否取消該線程

        {

            break;

        }

        System.Threading.Thread.Sleep(50);          //干點(diǎn)實(shí)際的事

        backgroundWorker.ReportProgress(i);         //報(bào)告進(jìn)度

    }

}






//線程進(jìn)度報(bào)告




private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)

{

    this.progressBar1.Value = e.ProgressPercentage * 100 / 150;

}






//線程結(jié)束報(bào)告




private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)

{            

    this.btnStart.Enabled = true;

    this.btnStop.Enabled = false;

}  
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 上林县| 台中县| 兰西县| 牙克石市| 堆龙德庆县| 集贤县| 繁昌县| 韶山市| 谢通门县| 通山县| 丽水市| 元氏县| 东辽县| 麟游县| 子洲县| 勐海县| 永清县| 桐城市| 濉溪县| 如东县| 曲阜市| 营山县| 盐边县| 桂平市| 揭西县| 永安市| 开原市| 苗栗市| 菏泽市| 宿迁市| 屏东县| 苍梧县| 曲水县| 尚志市| 余庆县| 津南区| 诸暨市| 兰西县| 天柱县| 松江区| 图们市|