大夢(mèng)想家

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

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

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

          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) + "個(gè)任務(wù)執(zhí)行完畢");
                              if (stopFlag) {// 監(jiān)控是否要讓停止后臺(tái)任務(wù)
                                  System.out.println("被中斷了");
                                  return;
                              }
                              try {
                                  Thread.sleep(1000);
                              } catch (Throwable t) {}
                          }
                          stopFlag = true;// 執(zhí)行完畢后把標(biāo)志位設(shè)為停止,好通知給進(jìn)度框
                          System.out.println("全部任務(wù)執(zhí)行完畢");
                      }

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

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

           

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

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

          new ProgressMonitorDialog(s).run(true, true, runnable);
          使用此句的話(huà),JFace的線(xiàn)程永遠(yuǎn)不會(huì)啟動(dòng);

          替換為

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

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

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

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

          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中說(shuō)的很明白,如果fork為false時(shí)需要在線(xiàn)程中調(diào)用Display.readAndDispatch()方法,以避免UI被阻塞!

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



          客戶(hù)虐我千百遍,我待客戶(hù)如初戀!

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

          評(píng)論

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

          這一點(diǎn)和win32api很像

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

          我把你的代碼拷過(guò)來(lái),用new ProgressMonitorDialog(s).run(true, true, runnable); 好像可以用啊,進(jìn)度條走了幾次就停下來(lái),cancel也可以,沒(méi)出什么問(wèn)題啊,我用swt3.3

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

          首先我上面貼的代碼是沒(méi)有問(wèn)題的!
          其次多看幾遍
          “我討論的進(jìn)度條主要是JFace的進(jìn)度條,RCP已經(jīng)提供了完善的Job組件,為什么還要用JFace的進(jìn)度條呢?原因是我要在登陸界面上做進(jìn)度處理,也就是使用Eclipse3.3提供的AbstractSplashHandler特性,可以將原有的啟動(dòng)畫(huà)面替換成為一個(gè)登陸界面,啟動(dòng)這個(gè)登陸界面時(shí),Eclipse的Platform此時(shí)還沒(méi)有啟動(dòng),所以不能使用RCP本身的Job組件了?!?/div>

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

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

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

          比javascript簡(jiǎn)約啊

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

          做個(gè)手機(jī)收發(fā)短信軟件
          主站蜘蛛池模板: 合肥市| 日喀则市| 白银市| 金昌市| 长丰县| 梓潼县| 加查县| 郯城县| 富宁县| 四会市| 神农架林区| 英德市| 云霄县| 平江县| 栖霞市| 洪洞县| 富源县| 讷河市| 伊通| 宣城市| 三原县| 建德市| 庆阳市| 讷河市| 庆云县| 岑巩县| 卢龙县| 恩施市| 红河县| 合作市| 五家渠市| 阜平县| 阿巴嘎旗| 乌兰察布市| 仙居县| 灌云县| 太谷县| 琼结县| 栖霞市| 外汇| 昭觉县|