SWT之syncExec與asyncExec

   SWT組件Diaplay提供syncExec與asyncExec方法,其原型爲:syncExec (Runnable runnable),asyncExec (Runnable runnable),Runnable的run方法中可以封裝要執行的代碼,一般而言是UI相關的代碼,如更新組件顯示、刷新狀態等。Diaplay是和線程關聯的,其所在的線程一般稱謂UI線程,可以有多個UI線程,每個UI線程一個Diaplay。所有的SWT組件相關代碼,必須在UI線程之中執行。
  
   syncExec與asyncExec相同點,都是爲了讓Runnable封裝的代碼在指定的Diaplay(比如某個產成Image的diaplay)相關的UI線程中執行。如:imgCreateDiaplay.asyncExec(runnable)。需要說明的是,當前線程一般是非UI線程,也可以是UI線程(如其它UI相關線程如awt UI線程,和爲提高執行效率,多個SWT UI線程之間協作併發執行,甚至調用線程和執行runnable的UI線程是同一個線程)
  
   syncExec與asyncExec不相同點體現在對方法調用線程本身的影響,syncExec阻塞當前線程直到UI線程完成runnable中的代碼執行;而asyncExec則直接返回,不等待runnable中代碼被執行,但並不是說asyncExec執行的代碼一定不在同一個線程中,有些時候是同一個線程,只不過將代碼的執行根據需要分成兩個部分或多個部分處理。
  
   兩者的異同決定了其分別適應不同的場合,一般syncExec適合在需要同步UI更新之後繼續執行的代碼,asyncExec適合在不便、不能syuncExec的情況下使用。
  
   syncExec適用情況比較簡單,以下總結asyncExec的適用情況。
  
   1、非UI線程需要調用在UI線程中調用的組件方法。非UI線程是相對與UI線程來講的,UI線程準確的講是diaplay變量所在的線程,因此非UI線程其實是非display所在的線程,其可以是任何其它線程,如UI無關的後臺作業處理線程、SWT-AWT共用應用中的awt所在線程、其它display線程(這種情況比較少,一般應用於服務程序,如大量生成圖片的多UI線程,相互之間協調時的調用,如幾個UI線程負責地圖圖片的繪製,然後交給另外一個UI線程做裝飾處理);
  
   2、跳出當前UI事件處理,安排後續事件。當前display所在的UI線程,在事件處理過程中,需要在執行完畢之後啓動另外一個UI處理過程,可以使用asyncExec,發起另外一個UI線程處理,結束當前的UI處理。有幾種情況下需要這麼做:A、當前事件處理必須執行完畢,使應用到達一定的狀態之後,做另外的UI處理,但是由於SWT、JFace或其它應用框架的存在,當前事件處理完成之後需要應用框架執行一些其它代碼之後纔可以執行另外的UI處理,否則會導致狀態不一致,界面出錯。但是當前事件處理完畢之後,不會出現其它事件來觸發需要另外執行的代碼,此時可以使用asyncExec,在框架的事件處理序列中插入另外一個事件,在當前事件處理完畢之後的某個時刻(一般很快)來執行;B、定時刷新或其它不是很重要的UI操作,通過asyncExec執行,不影響重要的UI事件處理。asyncExec所在的事件隊列優先級較低。
  
  3、事件比較密集,而且不均衡,有時非常密集,有時不太密集,爲了將事件處理均衡處理,使UI線程始終能夠應付自如,而不是延遲重要事件的處理、使用戶感到界面遲鈍現象,將不重要的事件放到低優先級序列中,從而保證用戶響應性,界面整體的有效性。
  
   asyncExec使用時需要注意的問題主要在於兩個方面。
   1、響應及時性。可以認爲SWT存在兩個事件隊列,正常UI事件隊列,需異步處理的隊列,該隊列優先級較低,asyncExec對應於SWT低優先級隊列,因此有可能在正常隊列事件較多、事件處理較慢的時候,asyncExec相關代碼不能及時執行的問題,從而導致響應不夠及時;
   2、多線程同步問題。假如某段事件處理代碼發出多個asyncExec請求,每個asyncExec代碼訪問同一個變量,假設該變量是整數,第一次發出請求是值爲1、第二次爲2、第三次爲3,所有請求發出,該事件處理完畢時,整數值爲5,隨後第一次發出的asyncExec請求執行,訪問整數變量,此時爲5,而本應該是1,其它幾個有類似問題。
  
  
   當然了,Display也提供了timerExec,可以將其理解爲Timer和asyncExec兩者的結合,代碼在指定時間之後異步執行。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章