asyncexec_如何安全使用SWT的显示器asyncExec
asyncexec
大多數用戶界面(UI)工具箱都是單線程的, SWT也不例外。 這意味著必須僅從單個線程(即所謂的UI線程)訪問UI對象。 另一方面,應在后臺線程中執行長時間運行的任務,以使UI保持響應。 這使得后臺線程需要排隊在UI線程上執行更新,而不是直接訪問UI對象。
為了安排代碼在UI線程上執行,SWT提供了Display asyncE?xec()和syncE?xec()方法。
顯示asyncE?xec與syncE?xec
雖然這兩種方法都將參數放在隊列中以便在UI線程上執行,但是它們在執行(或不執行)之后的操作有所不同。 顧名思義,asyncE?xec()異步工作。 它在可運行變量入隊后立即返回,并且不等待其執行。 而syncE?xec()正在阻塞,因此確實要等到代碼執行完畢。
根據經驗,只要不依賴計劃代碼的結果即可使用asyncE?xec(),例如僅更新小部件以報告進度。 如果計劃的代碼返回了與進一步控制流相關的內容(例如,在阻止對話框中提示輸入),那么我將選擇syncE?xec()。
例如,如果后臺線程要報告已完成工作的進度,則最簡單的形式可能如下所示:
progressBar.getDisplay().asyncE?xec( new Runnable() {public void r?un() {progressBar.setSelection( ticksWorked );} } );asyncE?xec()計劃“在下一個合理的機會”(如JavaDoc所說)在UI線程上執行可運行對象。
不幸的是,上面的代碼可能會不時地失敗,并會出現一個放置小部件的異常 ,或更確切地說是一個SWTException,其代碼== SWT.ERROR_WIDGET_DISPOSED。
因此,原因是,進度條在訪問時可能不再存在(即,調用setSelection())。 盡管我們仍然保留著對小部件的引用,但是由于小部件本身已被廢棄,因此并沒有太大用處。 解決方案顯而易見:代碼必須先測試該小部件是否仍然存在,然后再對其進行操作:
progressBar.getDisplay().asyncE?xec( new Runnable() {public void r?un() {if( !progressBar.isDisposed() ) {progressBar.setSelection( workDone );}} } );看起來很明顯,一次又一次地執行這種檢查是很乏味的。 您可能想在Eclipse bugzilla中搜索“ widget處置”,以了解此問題的發生頻率。 因此,我們提取了一個封裝檢查的輔助類。
new UIThreadSynchronizer().asyncE?xec( progressBar, new Runnable() {public void r?un() {progressBar.setSelection( workDone );}} );UIThreadSynchronizers asyncE?xec()方法期望將小部件作為充當上下文的第一個參數。 上下文小部件是指如果可運行的部件多于一個,則將受可運行部件或合適的父部件影響的部件。 在運行runnable之前,將檢查上下文小部件。 如果仍然有效(即未處置),則將執行代碼,否則,將靜默刪除該代碼。 盡管忽略已處置小部件的代碼的行為可能看起來很粗心,但它適用于到目前為止我們遇到的所有情況。
進行線程間通信的單元測試代碼特別難以測試。 因此,盡管UIThreadSynchronizer是無狀態的,但必須對其進行實例化以使其可以通過test double替換。
- 帶有相應測試的源代碼可以在這里找到: https : //gist.github.com/rherrmann/7324823630a089217f46
盡管示例使用了asncE?xec(),但UIThreadSynchronizer也支持syncE?xec()。 并且,當然,helper類也與RAP / RWT兼容。
如果您完整地閱讀了源代碼,您可能已經注意到可能存在爭用情況。 因為Widget類的所有方法都不是線程安全的,所以isDisposed()或getDisplay()返回的值可能是陳舊的(請參見第51 行和第60行 )。 當時故意將其忽略-閱讀:我沒有找到更好的解決方案。 盡管runnable可能會被錯誤地排隊,但isDisposed()-check(在UI線程上執行)最終將阻止代碼執行。
另外還有一個線程線程問題的機會(這是非常小的):在調用(a)syncE?xec()之前,檢查顯示器是否可處置,以免發生小部件處置異常。 但是,如果將顯示放置在檢查與(a)syncE?xec()調用之間,就可能發生這種情況。 盡管可以通過將調用包裝到忽略小部件處理的異常的try-catch塊中來解決asyncE?xec()的問題,但對于syncE?xec()而言,相同的方法將失敗。 無法通過合理的努力將可運行對象引發的SWTException與syncE?xec()引發的SWTException區別開來。
翻譯自: https://www.javacodegeeks.com/2014/09/how-to-safely-use-swts-display-asyncexec.html
asyncexec
總結
以上是生活随笔為你收集整理的asyncexec_如何安全使用SWT的显示器asyncExec的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 七大罪过与如何避免
- 下一篇: 手机微信聊天记录删除了怎么恢复电脑如何恢