還好,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);就可以了.
新聞熱點
疑難解答