amp@java

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            99 隨筆 :: 0 文章 :: 228 評論 :: 0 Trackbacks

          在SWT中,通常需要開多個線程來執行任務,因為主線程為UI線程,不能用太長的時間來執行某個任務,否則會造成失去響應的假象。
          SWT的線程通信有幾個要注意的地方:
          1、工作線程訪問UI線程。不能在非UI線程中直接訪問UI控件的值,要獲得或設置控件的值必須通過Display對象的asyncExec()或syncExec()函數,一般的使用方法是:

          //代碼A:
          ?
          Display?disp??
          = ??Display.getDefault();
          ?
          if ?(disp? != ? null ?)??{
          ???disp.asyncExec(
          ????
          new ??Runnable()??{
          ????
          public ?? void ??run()??{
          ???????
          // ?在這里設置或獲得控件的值?
          ?}?
          }?
          );?
          }?

          2、內部類與外部類的交流。內部類調用外部類局部變量時,該變量必須是final的,這樣在取得控件的值后返回給外部類處理時就比較麻煩。例如,在上面的代碼段中,有個匿名內部類實現了Runnable接口,在里面的run()函數里可以訪問到UI對象,但是,得到了對象的值怎么告訴外面的代碼呢?假如用普通的局部變量傳遞進去,由于是final的,是不能賦值的,所以需要有一個封裝類來把需要返回的變量封裝起來,這個封裝類是final的,但里面的成員變量是可變的,這樣就把內部類里得到的東西傳遞到了外部,不過似乎比較麻煩,不知道有沒有更好的辦法。
          //代碼B:

          class
          ?StringWrapper?{
          ???public?String?uiValue;
          }
          StringWrapper?sw?
          =?new?StringWrapper();?
          Display?disp??
          =??Display.getDefault();
          ?
          if?(disp?!=?null?)??{
          ???disp.asyncExec(
          ????
          new??Runnable()??{
          ????
          public??void??run()??{
          ????????sw.uiValue?
          =?text.getText();//假設text是一個文本框對象
          ???????
          //?在這里設置或獲得控件的值?
          ????}?
          ???}?
          ???);?
          }?
          //這里就可以對sw.uiValue的值進行訪問
          3、線程間的同步。在上面的代碼B中,通過asyncExec()函數來取得控件的值所需要的時間比較長,如果在后面馬上訪問那些值是得不到的,于是就需要有個同步的問題,即在控件值取得之前先不進行下一步操作。可以通過synchronized塊及wait(),notify()機制來實現同步。

          //代碼C:

          class?StringWrapper?{
          ???
          public?String?uiValue;
          }
          StringWrapper?sw?
          =?new?StringWrapper();?
          Display?disp??
          =??Display.getDefault();
          ?
          if?(disp?!=?null?)??{
          ???disp.asyncExec(
          ????
          new??Runnable()??{
          ????
          public??void??run()??{
          ????????
          synchronized(sw){
          ??????????sw.uiValue?
          =?text.getText();//假設text是一個文本框對象
          ????????????sw.notify();
          ?????????}
          ???????
          //?在這里設置或獲得控件的值
          ?
          ????}?
          ???}?
          ???);?
          }
          synchronized(sw){
          ??sw.wait();
          }?
          //這里就可以對sw.uiValue的值進行訪問

          但是這里會帶來一個問題,假如很快就能取得控件的值,但后面還有很長一段時間才會用到該值,如果把sw.wait()語句放在比較后的地方,就有可能造成死鎖,因為sw已經被notify之后才開始wait的,再沒有其他線程來notify它了,它就只能一直wait下去……。為了解決這個問題,可以(1)把sw.wait()緊跟在disp.asyncExec()后面;(2)給wait()設置一個timeout參數,到了一定的時間還沒有東西notify它,它就自己超時。但這兩種辦法似乎都比較牽強,沒有十足的保證,JDK文檔里面有個例子,是用while來判斷是否已經達到了要求,如果已經達到了就不再wait。
          //代碼D:

          class?StringWrapper?{
          ???
          public?String?uiValue;
          ???
          public?boolean?isValueSet;//是否已經取得了控件的值
          }
          StringWrapper?sw?
          =?new?StringWrapper();?
          sw.isValueSet?
          =?false;
          Display?disp??
          =??Display.getDefault();
          ?
          if?(disp?!=?null?)??{
          ???disp.asyncExec(
          ????
          new??Runnable()??{
          ????
          public??void??run()??{
          ????????
          synchronized(sw){
          ??????????sw.uiValue?
          =?text.getText();//假設text是一個文本框對象
          ????????????sw.isValueSet?=?true;
          ????????????sw.notify();
          ?????????}
          ???????//?在這里設置或獲得控件的值

          ?
          ????}?
          ???}?
          ???);?
          }
          synchronized(sw){
          ??
          while(!sw.isValueSet){
          ????
          try{
          ??????sw.wait();
          ????}
          catch?(InterruptedException?e){
          ????}
          ??}
          }?
          //這里就可以對sw.uiValue的值進行訪問


          posted on 2006-03-27 17:29 amp@java 閱讀(1007) 評論(0)  編輯  收藏 所屬分類: SWT

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 济南市| 孝感市| 新安县| 巫山县| 阳山县| 大洼县| 乌苏市| 靖西县| 新营市| 章丘市| 西充县| 陆良县| 西乌| 东阿县| 普兰店市| 贵南县| 卓尼县| 冀州市| 泗阳县| 水城县| 吉林市| 皮山县| 灵武市| 新宁县| 嫩江县| 富平县| 淮滨县| 铁力市| 漾濞| 格尔木市| 苏尼特左旗| 隆子县| 玛曲县| 尚志市| 同德县| 博白县| 德令哈市| 克东县| 新昌县| 高雄市| 西乌珠穆沁旗|