大夢想家

          5年開發(fā)工程師,2年實施經(jīng)理,X年售前顧問,......
          數(shù)據(jù)加載中……
          JFace進度條使用經(jīng)驗一則

              我討論的進度條主要是JFace的進度條,RCP已經(jīng)提供了完善的Job組件,為什么還要用JFace的進度條呢?原因是我要在登陸界面上做進度處理,也就是使用Eclipse3.3提供的AbstractSplashHandler特性,可以將原有的啟動畫面替換成為一個登陸界面,啟動這個登陸界面時,Eclipse的Platform此時還沒有啟動,所以不能使用RCP本身的Job組件了。

              由于是一個檢測服務(wù)器是否聯(lián)通的測試,所以并不知道測試的真實時間,所以就是要使用“傻瓜進度條”了,也就是反復(fù)走的進度條陳剛的代碼如下:

          button.addSelectionListener(new SelectionAdapter() {
                      private boolean stopFlag;// 停止標(biāo)志

                      private void go() {
                          for (int i = 0; i < 10; i++) {// 循環(huán)10次,每次間隔一秒
                              System.out.println("第" + (i + 1) + "個任務(wù)執(zhí)行完畢");
                              if (stopFlag) {// 監(jiān)控是否要讓停止后臺任務(wù)
                                  System.out.println("被中斷了");
                                  return;
                              }
                              try {
                                  Thread.sleep(1000);
                              } catch (Throwable t) {}
                          }
                          stopFlag = true;// 執(zhí)行完畢后把標(biāo)志位設(shè)為停止,好通知給進度框
                          System.out.println("全部任務(wù)執(zhí)行完畢");
                      }

                      public void widgetSelected(SelectionEvent e) {
                          stopFlag = false;// 每次都設(shè)初值為false
                          new Thread() {// 把后臺任務(wù)放到一個新開線程里執(zhí)行
                              public void run() {
                                  go();
                              }
                          }.start();
                          showProgressDialog();// 打開一個進度框
                      }

                      private void showProgressDialog() {
                          IRunnableWithProgress runnable = new IRunnableWithProgress() {
                              public void run(IProgressMonitor monitor) {
                                  monitor.beginTask("正在執(zhí)行中......", 30);
                                  int i = 0;
                                  while (true) {
                                      // 監(jiān)聽是否單擊了進度框的“取消”按鈕,stopFlag則是監(jiān)聽后臺任務(wù)是否停止
                                      if (monitor.isCanceled() || stopFlag) {
                                          stopFlag = true; // 單擊了“取消”按鈕要設(shè)標(biāo)志位為停止,好通知后臺任務(wù)中斷執(zhí)行
                                          break;// 中斷處理
                                      }
                                      // i到30后清零。并將進度條重新來過
                                      if ((++i) == 30) {
                                          i = 0;
                                          monitor.beginTask("正在執(zhí)行中......", 30);
                                      }
                                      // 進度條每前進一步體息一會,不用太長或太短,時間可任意設(shè)。
                                      try {
                                          Thread.sleep(99);
                                      } catch (Throwable t) {}
                                      monitor.worked(1);// 進度條前進一步
                                  }
                                  monitor.done();// 進度條前進到完成
                              }
                          };
                          try {
                              new ProgressMonitorDialog(s).run(true, true, runnable);
                          } catch (Exception e) {
                              e.printStackTrace();
                          }
                      }
                  });

           

              主要是使用兩個線程交替使用,第一個線程處理業(yè)務(wù),第二個線程監(jiān)控第一個線程查看它是否結(jié)束,如果結(jié)束或者被點擊cancele則停止進度條的進程,如果一直沒有關(guān)閉的指令,則反復(fù)開始---累加---結(jié)束---開始---累加---結(jié)束。

              我們幾乎是把陳剛的代碼原原本本的抄襲了一下,僅僅是替換了go()中的內(nèi)容,但是發(fā)現(xiàn)一個問題

          new ProgressMonitorDialog(s).run(true, true, runnable);
          使用此句的話,JFace的線程永遠不會啟動;

          替換為

          new ProgressMonitorDialog(s).run(false, true, runnable);
          使用此句的話,JFace的線程可以啟動,運行正常,但是cancele不能響應(yīng),UI界面完全卡死!

              第一個參數(shù)的名字fork~乍看去,什么意思都沒有,但是看看API才發(fā)現(xiàn)內(nèi)藏很大的玄機,如果為true則此線程為一個非UI線程,大家知道非UI線程是不會阻塞UI的;如果為false則此線程為一個UI線程,大家也知道UI線程如果使用不當(dāng)很容易阻塞UI的。

              關(guān)鍵的問題是我們和陳剛的代碼幾乎一摸一樣他的進度條就啟動,我的進度條就不啟動!為什么?(這點至今不明白!)

              詳查API發(fā)現(xiàn)如果fork為false的時候還是另有洞天的:

          This implementation of IRunnableContext#run(boolean, boolean, IRunnableWithProgress) runs the given IRunnableWithProgress using the progress monitor for this progress dialog and blocks until the runnable has been run, regardless of the value of fork. The dialog is opened before the runnable is run, and closed after it completes. It is recommended that fork is set to true in most cases. If fork is set to false, the runnable will run in the UI thread and it is the runnable's responsibility to call Display.readAndDispatch() to ensure UI responsiveness.

          API中說的很明白,如果fork為false時需要在線程中調(diào)用Display.readAndDispatch()方法,以避免UI被阻塞!

          大家如果在JFace的開發(fā)中如果使用了進度條,發(fā)現(xiàn)UI被阻塞的話,就想想我哦!!!呵呵只用在進程中調(diào)用一下Display.readAndDispatch()就解決了!



          客戶虐我千百遍,我待客戶如初戀!

          posted on 2008-02-29 08:47 阿南 閱讀(3830) 評論(6)  編輯  收藏 所屬分類: Eclipse-SWT個人原創(chuàng)

          評論

          # re: JFace進度條使用經(jīng)驗一則 2008-02-29 10:12 香草的天空

          這一點和win32api很像
            回復(fù)  更多評論    

          # re: JFace進度條使用經(jīng)驗一則 2008-02-29 13:43 Matthew Chen

          我把你的代碼拷過來,用new ProgressMonitorDialog(s).run(true, true, runnable); 好像可以用啊,進度條走了幾次就停下來,cancel也可以,沒出什么問題啊,我用swt3.3
            回復(fù)  更多評論    

          # re: JFace進度條使用經(jīng)驗一則 2008-02-29 17:26 阿南

          首先我上面貼的代碼是沒有問題的!
          其次多看幾遍
          “我討論的進度條主要是JFace的進度條,RCP已經(jīng)提供了完善的Job組件,為什么還要用JFace的進度條呢?原因是我要在登陸界面上做進度處理,也就是使用Eclipse3.3提供的AbstractSplashHandler特性,可以將原有的啟動畫面替換成為一個登陸界面,啟動這個登陸界面時,Eclipse的Platform此時還沒有啟動,所以不能使用RCP本身的Job組件了。”
            回復(fù)  更多評論    

          # re: JFace進度條使用經(jīng)驗一則 2008-03-01 10:01 pice

          在go()方法中你用一個for循環(huán)來假設(shè)正在執(zhí)行的業(yè)務(wù)調(diào)用,如果go方法中就一個方法調(diào)用,但是這個方法執(zhí)行時間比較長。private void go() {
          dbSelectList();//查詢數(shù)據(jù)庫,查詢時間大約10秒
          stopFlag = true;// 執(zhí)行完畢后把標(biāo)志位設(shè)為停止,好通知給進度框
          System.out.println("全部任務(wù)執(zhí)行完畢");
          }
          這時進度條的cancel按鈕就不起作用了,不管是否點擊cancel按鈕dbSelectList()方法都將執(zhí)行完畢后進度條才注銷。就算是重寫進度條的cancelPressed()方法關(guān)閉UI線程使得進度條界面“消失”,但是dbSelectList()方法還是會繼續(xù)執(zhí)行完。
          進度條能應(yīng)對這樣的情況嗎?
            回復(fù)  更多評論    

          # re: JFace進度條使用經(jīng)驗一則 2008-03-02 14:46 xifu

          比javascript簡約啊
            回復(fù)  更多評論    

          # re: JFace進度條使用經(jīng)驗一則 2010-05-09 10:38 靈均

          做個手機收發(fā)短信軟件
            回復(fù)  更多評論    
          主站蜘蛛池模板: 连南| 四川省| 建德市| 牡丹江市| 湖口县| 延安市| 新泰市| 方正县| 佛坪县| 扎兰屯市| 陆河县| 北票市| 苍梧县| 临夏市| 河津市| 文登市| 罗源县| 太和县| 炉霍县| 罗江县| 江安县| 长宁县| 罗源县| 陇西县| 平远县| 泰来县| 紫金县| 黑山县| 托克逊县| 库车县| 锦屏县| 汾西县| 荃湾区| 临沭县| 咸阳市| 昌江| 阿合奇县| 彰武县| 尼勒克县| 瑞昌市| 北宁市|