還好,eclipse為我們開發插件提供了一個方便的ui線程包,大大的簡化了很多底層復雜的東西.先看看幾個簡單的概念.
  1.swt ui線程
  swt用的是操作系統直接支持的線程模式,程序會在主程序里運行一個時間循環并依次在這個線程里響應事件.看下面這段代碼,ui線程就是創建display的那個線程.
public static void main (string [] args) {
      display display = new display ();
      shell shell = new shell (display);
      shell.open ();
      // 開始事件循環
      // 關掉窗口后
      while (!shell.isdisposed ()) {
         if (!display.readanddispatch ())
            display.sleep ();
      }
      display.dispose ();
   }
  簡單的小程序里,一個ui線程就能夠滿足需要了。但如果是長時間的操作,你就最好不要用ui線程來做這些事,可以交給job去做.它其實就是另外啟動的線程,也就是等會我要說的非ui線程.
  2、job
  job類由org.eclipse.core.runtime插件提供.它能夠讓客戶程序員輕松的在另外的線程中執行代碼。看一個小例子:
  job job = new job("my first job") {
     protected istatus run(iprogressmonitor monitor) {
           system.out.println("hello world (from a background job)");
           return status.ok_status;
        }
     };
  job.setpriority(job.short);
  job.schedule(); // start as soon as possible
  job的默認優先級是job.long,這里例子中的優先級要比它高,只要調用job#schedule(),它就會盡快在另外的線程中運行run()中的代碼。再看一個小例子:
final job job = new job("long running job") {
        protected istatus run(iprogressmonitor monitor) {
           try {
              while(hasmoreworktodo()) {
                 // do some work
                 // ...
              if (monitor.iscanceled()) return status.cancel_status;
             }
              return status.ok_status;
           } finally {
              schedule(60000); // start again in an hour
           }
        }
     };
  job.addjobchangelistener(new jobchangeadapter() {
        public void done(ijobchangeevent event) {
        if (event.getresult().isok())
           postmessage("job completed successfully");
           else
              posterror("job did not complete successfully");
        }
     });
  job.setsystem(true);
     job.schedule(); // start as soon as possible
  monitor是一個進度顯示條,它會在運行job時自動顯示,如果任務成功運行完成,返回status.ok_status,如果中途被用戶在進度顯示條那里中斷,就返回status.cancel_status.上面schedule(60000);它是讓job每過1小時就自動運行,job又一個非常強大的功能。然后后面是可以給job添加監聽器,
job.setsystem(true);這一句是把這個job設置為系統級別的.如果調用setuser(true),那么就被定義為用戶級別的,用戶級別和默認級別的job。
  在運行時會以ui形式反映出來,如果是用戶job,那么會彈出一個進度顯示窗口,能讓用戶選擇在后臺里運行,下圖是一個job自動運行時的效果:
 
  再介紹job常常用到的一個方法job#join(),系統調用到某個job,調用它的run()方法。再看下面這個例子:
    class trivialjob extends job {
      public trivialjob() {
         super("trivial job");
      }
      public istatus run(iprogressmonitor monitor) {
         system.out.println("this is a job");
         return status.ok_status;
      }
   }
   
  job的創建和計劃如下所示:
   trivialjob job = new trivialjob();
   system.out.println("about to schedule a job");
   job.schedule();
   system.out.println("finished scheduling a job");
   
  他們的執行是和時間沒關系的,輸出可能如下:
   about to schedule a job
   this is a job
   finished scheduling a job
也可能是:
   about to schedule a job
   finished scheduling a job
   this is a job
   
  如果希望某個job運行完成后在繼續時,可以使用join()方法,join()會一直阻塞到該job運行完。
   
  例子:
   trivialjob job = new trivialjob();
   system.out.println("about to schedule a job");
   job.schedule();
   job.join();
   if (job.getresult().isok())
      system.out.println("job completed with success");
   else
      system.out.println("job did not complete successfully");
上面的代碼執行后,輸出應該就是這樣:
 about to schedule a job
   this is a job
   job completed with success
  job的功能是很強大的,還有很多功能我以后會介紹,也可以查閱官方幫助文檔,這里先把幾個常用的問題解決掉。參見:
http://help.eclipse.org/help30/index.jsp?topic=/org.eclipse.platform.doc.isv/guide/runtime_jobs.htm
  3、如果在job中加上改變ui的代碼就會失敗。原因如下:
  如果是在非ui線程中調用ui,swt就會拋出一個swtexception,要在一個非ui線程改變ui的話有幾種技術:
  第一種,用:
display#syncexec(runnable)或
diaplay#asyncexec(runnable)
  第二種:
  已經開發了另外一種job,就是uijob,可以直接在它里面運行改變ui的代碼,其實它就是在swt的asyncexec()方法里運行的.所有繼承uijob的類應該覆寫runinuithread方法而不是run方法。
  3.關于進度顯示
  在jface中:
  org.eclipse.jface.operations包定義了一些接口用來在進度條下運行長時間的任務。可以參見:
http://help.eclipse.org/help30/index.jsp?topic=/org.eclipse.platform.doc.isv/guide/jface_operations.htm
  在eclipse插件和rcp開發中:
  用戶級別的job是互操作性最強的,它不僅能夠讓用戶用cancel鍵取消job,而且可以在detail中展示具體情況,但是注意:
  detail只會在下面兩種方法中出現:
  iprogressservice#busycursorwhile或
  iprogressservice#runinui
  1)iprogressservice#busycursorwhile的用法例子:
  注意這里的run()中做些和ui無關的事:
iprogressservice progressservice = platformui.getworkbench().getprogressservice();
   progressservice.busycursorwhile(new irunnablewithprogress(){
      public void run(iprogressmonitor monitor) {
         //do non-ui work
      }
   });
  效果:
  2) iprogressservice#runinui的用法例子:
  注意這里的run()中可以做些和ui有關的事。
progressservice.runinui(
      platformui.getworkbench().getprogressservice(),
      new irunnablewithprogress() {
         public void run(iprogressmonitor monitor) {
            //do ui work
         }
      },
      platform.getworkspace().getroot());
  效果:
  這里最后一個參數可以是null,或者是這個操作的規則,在這里我們是設定運行這個ui操作時鎖定工作臺.
  更加具體的可以參見:
http://help.eclipse.org/help30/index.jsp?topic=/org.eclipse.platform.doc.isv/guide/workbench_jobs.htm
另外,有少數時候,我們不想彈出一個進度條窗口,而是只在最底下的狀態欄顯示就可以了,很簡單,寫自己的job類時,在構造方法里加上一句:setuser(false);就可以了.
新聞熱點
疑難解答