标签:style http color java os io ar art
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 ();
}
while循环一段就是处理消息循环的开始,也就是说,一个SWT程序的主线程,就是对应的所谓的UI线程。
Label label = new Label (shell, SWT.NONE);
label.setText ("Enter your name:");
Text text = new Text (shell, SWT.BORDER);
text.setLayoutData (new RowData (100, SWT.DEFAULT));
Button ok = new Button (shell, SWT.PUSH);
ok.setText ("OK");
ok.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
while(true) {
System.out.println(1);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
});
程序中模拟在点击按钮后,执行一段费时的操作,运行可以看到,程序处于无响应状态:
那么,如何避免程序进入无响应状态呢? 其实很简单,不要在UI线程中执行长时间的操作,如果必需要执行费时操作,就在另外的线程中执行:
ok.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
new Thread() {
public void run() {
while(true) {
System.out.println(1);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}.start();
}
});
这样再次执行,可以看到点击按钮后,程序不再会进入无响应状态。
所以对控件的操作都必需在UI线程中进行,否则会抛出线程访问错误,还是以上面代码为例,我们现在改成打印text控件的文本:
ok.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// 此处代码直接在监听器方法中,是UI线程
new Thread() {
public void run() {
// 此处为另外一个单独线程,非UI线程
while(true) {
System.out.println(text.getText());
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}.start();
}
});
运行程序,点击按钮,就会抛出下面的异常:
Exception in thread "Thread-0" org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(SWT.java:4441)
at org.eclipse.swt.SWT.error(SWT.java:4356)
at org.eclipse.swt.SWT.error(SWT.java:4327)
at org.eclipse.swt.widgets.Widget.error(Widget.java:476)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:367)
at org.eclipse.swt.widgets.Text.getText(Text.java:1350)
at test.Snippet108$1$1.run(Snippet108.java:24)
对于这种在非UI线程访问UI的情况,需要用Display类的syncExec(Runnable)或asyncExec(Runnable)两个方法来执行:
ok.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// 此处代码直接在监听器方法中,是UI线程
new Thread() {
public void run() {
// 此处为另外一个单独线程,非UI线程
while(true) {
// 非UI线程访问UI
display.syncExec(new Runnable() {
@Override
public void run() {
// 这段代码实际上会被放在UI线程中执行
System.out.println(text.getText());
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
}.start();
}
});
注意上面的注释说明,syncExec(runnable)方法的参数runnable对象实际上是会被放在UI线程中执行的,所以要注意,不要把Tread.sleep()放到这个runnable里,否则同样会导致界面无响应。
syncExec和asyncExec方法的区别就是这两个方法一个会等待runnable执行完才返回,asyncExec方法则是立即返回,UI线程会在有空闲的时候去执行runnable。
那么,是否能够用asyncExec方法执行,同时把上面的sleep放到runnable中呢? 答案依然是不能,原因前面已经提到了,因为runnable实际上是会放到UI线程中执行的,如果这个runnable是非常耗时的,同样会让界面不断陷入每次1秒的无响应状态中, 也相当于新开一个线程执行耗时操作的目的就没有达到了。
读者可以试着根据上面的例子,自己写一个时钟程序,每秒钟刷新显示当前时间,注意不要让程序陷入无响应状态。 可以参考示例代码。
标签:style http color java os io ar art
原文地址:http://blog.csdn.net/dollyn/article/details/38582743