周嵐
摘 要:通常我們使用異步完成許多計算型的耗時操作,取得應用程序運行所需要的部分數據,再將它們綁定在UI中呈現,這個過程由于數據量偏大,窗體會出現“失去響應”的情況,而線程技術的使用可以方便的實現并發(fā)執(zhí)行,提升資源的利用率,提高程序處理效率,解除“假死”這種糟糕的體驗。本文通過對C#多線程技術及委托方法的介紹,分析研究了在WinForm窗體開發(fā)中解決假死狀態(tài)的兩種方法,給出實例及相關代碼,并對這兩種方法的特點進行了總結。
關鍵詞:多線程;假死;委托;BackGroundWorker控件
中圖分類號:TP311.11 文獻標識碼:A
Abstract:Asynchronous manners are usually adopted to implement lots of time-consuming computing operation,in order to achieve the data required by the application and bind them to be presented in UI.Due to the great amount of data,the form often stops responding.The multi-thread technology can facilitate the implementation of concurrency,promote the resource utilization,improve processing efficiency,and avoid the terrible experience of "suspended animation".Based on the C# multi-thread technology and principal methods,the paper analyzes two solutions to the problems of suspended animation in the WinForm development,provides examples and related code,and summarizes the characteristics of two solutions.
Keywords:multi-threading;suspended animation;commission;BackGroundWorker widget
1 引言(Introduction)
通常我們使用異步完成許多計算型、IO型的復雜、耗時操作,去取得我們的應用程序運行所需要的一部分數據[1]。在取得這些數據后,我們需要將它們綁定在UI中呈現。當數據量偏大時,我們會發(fā)現窗體變成了空白面板。此時如果用鼠標點擊,窗體標題將會出現“失去響應”的字樣,而實際上UI線程仍在工作著,這對用戶來說是一種極度糟糕的體驗。
我們打個比方:比如在上傳圖片的時候,我們會對上傳成功的圖片再進行一些相關的處理,一般保存原圖,再生成一張小圖給一些應用做預覽圖。如果讀取原圖再處理的過程由應用程序實現,讀取原圖需要時間為1秒,處理圖片需要2秒,現在有5張大圖,所需要花費的時間就是(1+2)*5=15秒,根據圖片的不同,那么單位時間會更多,總計時間就會更久,如果有一百萬張圖要進行相同的處理,那么我們等待的時間將會是15*1000000秒,大約是174天,這種等待是不是有點兒無法忍受。
那么,我們是不是可以把程序設計更好一點兒,讓應用程序在讀取文件的時候同時處理上一個已讀入的文件,這樣就好像是同時在做兩件事情,一邊燒開水,一邊打毛衣,可以盡可能的縮短時間。多線程的引入可以幫助應用程序實現這種更理想的狀態(tài),減少客戶端的響應,同時也提升了CPU的使用率。
2 線程(Threads)
在CPU制造工藝已經達到了物理極限的今天,除非技術有質的突破來進一步提高處理器的速度,但是,我們所要處理的數據量卻沒有一刻停止它飛速增長的腳步,所以,并行處理技術將成為未來發(fā)現的趨勢,并行處理技術的核心是對線程的操作[2]。線程,作為輕量級進程(Lightweight Process,LWP),是程序執(zhí)行流的最小單元,多線程是指從軟件或者硬件上實現多個線程并發(fā)執(zhí)行的技術。
其實,在開發(fā)的應用軟件中,大多數線程的數量都不止一個,多個線程可以并發(fā)的執(zhí)行,共享進程的全局變量和堆的數據。它的優(yōu)勢在于,當某個操作陷入長時間的等待,或者,一些計算可能會消耗大量的時間,這時會出現和用戶之間的交互中斷,如果采用多線程,一個線程等待(負責計算)的時候,其他線程可以執(zhí)行(另一個線程負責交互),保證CUP的利用率[3]。下面我們來具體看看,多線程在WinForm窗體開發(fā)中是如何解除假死的。
3 解決假死的方法(The method to solve the dead)
什么是假死呢?凡是WinForm的應用程序,如果程序執(zhí)行的是一個非常冗長的處理操作(比如文件查詢、批量的計算、大量文件的上傳或下載等),程序在執(zhí)行的時候,用戶界面會被鎖定,雖然主活動窗口一直在運行,但用戶沒有辦法與程序進行交互,窗體的位置和大小也不能移動和改變,就好像“死”在那里不能動一樣,用戶不能產生良好的使用體驗[4]。如何做才能使得這個程序有響應,消除這種“假死”的狀態(tài)呢?答案就是在后臺線程中執(zhí)行這個操作。現在介紹兩種方法來消除這種“假死”的現象。一種是利用BackgroundWorker控件實現;另一種是采用線程加委托的方法消除“假死”。下面我們分別來進行介紹。
3.1 利用BackGroundWorker 控件解除假死
使用BackgroundWorker控件可以在后臺單獨的線程上執(zhí)行操作,通常用于數據庫操作、文件下載等相對耗時一般要求后臺處理的任務,使用起來比較簡單[5]?,F在我們用BackGroundWorker控件設計一個模擬1000個文件復制過程的進度條,當我們點擊“文件復制模擬”按鈕時,進度條會顯示“正在復制”字樣,以及完成復制的百分比,如圖1所示,這樣做的好處是:用戶可以隨時了解應用程序執(zhí)行的進度,而不至于陷入盲目焦躁的等待。
3.2 采用線程加委托的方法解決假死
前面我們說過,在winform開發(fā)時,如果要對某控件顯示的內容進行操作,而這些內容的來源很耗時,會阻塞UI主線程,造成界面的假死,在操作完成之前,界面是不能接收任何響應的。我們可以采用線程+異步委托的方法來確保,即便是耗時的數據操作也不會影響UI的顯示和操作的流暢性[6]。
現在想模擬一個圖片上傳的功能,當點擊上傳按鈕時,彈出“上傳文件進度“對話框;當上傳結束后,對話框自動關閉。如圖2所示。
當文件上傳成功后,調用UI線程上的closeTip方法,關閉窗體2。
跨線程直接訪問控件在C#中是被禁止,還好我們有InvokeRequired,用它就可以解決這個問題。當一個控件的InvokeRequired屬性值為真時,說明有一個創(chuàng)建它以外的線程想訪問它。此時它將會在內部調用new MethodInvoker(LoadGlobalImage)來完成下面的步驟,這個做法保證了控件的安全[7]。舉個例子更如易理解,假如有人想找你借錢,他可以直接在你的錢包中拿嗎?這樣是不是太不安全了?所以,必須讓別人先要告訴你,你再從自己的錢包把錢拿出來借給別人,這樣更安全,也更合乎邏輯。
4 結論(Conclusion)
本文通過對C#多線程技術及委托方法的介紹,分析了在WinForm窗體開發(fā)中出現假死狀態(tài)的原因,并且詳細的說明了如何使用BackGroundWorker控件解除假死,以及如何采用線程加異步委托的方法解決假死。當然,在實際的開發(fā)過程中解除假死的方法還有很多,比如我們也可以利用Application.DoEvents()來解決這個問題[8]。當然,多線程并非是程序員的圣杯,使用起來也并非一勞永逸,它的使用會增加的內存負擔、要求CUP有更強的處理能力、“死鎖”也是不可回避的、如果不使用合理的同步結構,以保證獨占的數據訪問方式,那么,數據損壞也是多線程處理所要面對的一個巨大問題等等。對于以上問題,我們可以對此進行更深入的研究[9]。隨著制造水平的提高和技術的發(fā)展,CPU已經進入了超線程、多核的時代,相信在不久的未來,我們一定可以用更優(yōu)化的方式,設計出更加實用的、高效的應用程序,帶給用戶全新的操作體驗。
參考文獻(References)
[1] CAI Yunfei,TANG Zhenmin,ZHAO Chunxia.New Layered SOA-Based Architecture for Multi-Robots Cooperative Online SLAM[J].Chinese Journal of Electronics,2014, 01:25-30.
[2] Chen.S.M.,J.M.Tan.Handling Multicriteria Fuzzy Decision-Making Problems Based on VagueSet-Theory[J].Fuzzy SetsandSystems,1994,67(2):163-172.
[3] Colvin,J.,Tobler,N.,Anderson,J.A..Productivity and Multiscreen Computer Displays[J].Rocky Mountain Communication Review,2007,2(01):31-53.
[4] 龐麗萍.操作系統(tǒng)原理(第四版)[M].北京:華中科技大學出版社,2015.
[5] (美)斯托林斯.陳向群,譯.操作系統(tǒng):精髓與設計原理(原書第6版)[M].北京:機械工業(yè)出版社,2010.
[6] (美)Andrew Troelsen.精通C#(第6版)[M].北京:人民郵電出版社,2013.
[7] (英)里·麥克萊恩·霍爾(Gary McLean Hall).C#敏捷開發(fā)實踐[M].北京:人民郵電出版社,2016.
[8] (美)阿壩哈瑞,(美)阿壩哈瑞.著果殼中的C#——C#50權威指南[M].北京:水利水電出版社,2013.
[9] 秦婧.構建高質量的C#代碼[M].北京:清華大學出版社,2011.
作者簡介:
周 嵐(1977-),女,碩士,副教授.研究領域:程序設計,軟件開發(fā)與數據庫.