还好,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);就可以了.
新闻热点
疑难解答