Java:NullPointerException尝试从其他线程更新SWT标签时
通过阅读SO和其他在线来源(例如),我了解到您无法从其他线程访问SWT对象。Java:NullPointerException尝试从其他线程更新SWT标签时,java,multithreading,swt,Java,Multithreading,Swt,通过阅读SO和其他在线来源(例如),我了解到您无法从其他线程访问SWT对象。 事实上,当我尝试这样做时: 类菜单: public class Menu { public static void main(String args[]) { System.out.println("Main thread: "+Thread.currentThread().getId()); // prints 1 final Display display=new Di
事实上,当我尝试这样做时: 类菜单:
public class Menu {
public static void main(String args[]) {
System.out.println("Main thread: "+Thread.currentThread().getId()); // prints 1
final Display display=new Display();
final Shell shell=new Shell(display);
Label l=new Label(shell, SWT.SHADOW_IN);
l.setText("Some label");
l.pack();
SecondThread second_thread=new SecondThread(l);
Thread t=new Thread(second_thread);
t.start();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
}
第二类线程:
public class SecondThread implements Runnable {
private Label label;
public SecondThread(Label l) {
label=l;
}
@Override
public void run() {
System.out.println("Second thread: "+Thread.currentThread().getId()); // prints 8
for (int i=0; i<10000; ++i) {
try {
Thread.sleep(3000); // waiting three seconds...
} catch (InterruptedException e) {
e.printStackTrace();
}
label.setText("i is: "+i); // SWTException is thrown here
}
}
}
public class SecondThread implements Runnable {
private Label label;
public SecondThread(Label l) {
label=l;
}
@Override
public void run() {
System.out.println("Second thread: "+Thread.currentThread().getId()); // prints 8
for (int i=0; i<10000; ++i) {
try {
Thread.sleep(3000); // waiting three seconds...
} catch (InterruptedException e) {
e.printStackTrace();
}
updateLabel("i is: "+i);
}
}
private void updateLabel(final String string) {
Display display=Display.getCurrent(); // display is not null...
display.asyncExec(new Runnable() { // throws NullPointerException...
@Override
public void run() {
System.out.println("test");
label.setText(string);
}
});
}
}
这里以及其他在线资源中建议的解决方案是使用Display的asyncExec()
方法,该方法:
使runnable的run()方法由
用户界面线程在下一个合理的机会。来电者
此方法的一部分将继续并行运行,并且在
runnable已完成。简单地将null指定为可运行
运行时唤醒用户界面线程
所以我试着替换:
SecondThread second_thread=new SecondThread(l);
Thread t=new Thread(second_thread);
t.start();
与:
SecondThread second_thread=new SecondThread(l);
display.asyncExec(second_thread);
但事实证明,这并没有真正创建新的执行线程,正如输出所示:
Main thread: 1
Second thread: 1
因此,Thread.sleep(3000)
调用会使GUI窗口无响应
所以我尝试了一种不同的方法:
菜单:
第二个线程:
public class SecondThread implements Runnable {
private Label label;
public SecondThread(Label l) {
label=l;
}
@Override
public void run() {
System.out.println("Second thread: "+Thread.currentThread().getId()); // prints 8
for (int i=0; i<10000; ++i) {
try {
Thread.sleep(3000); // waiting three seconds...
} catch (InterruptedException e) {
e.printStackTrace();
}
label.setText("i is: "+i); // SWTException is thrown here
}
}
}
public class SecondThread implements Runnable {
private Label label;
public SecondThread(Label l) {
label=l;
}
@Override
public void run() {
System.out.println("Second thread: "+Thread.currentThread().getId()); // prints 8
for (int i=0; i<10000; ++i) {
try {
Thread.sleep(3000); // waiting three seconds...
} catch (InterruptedException e) {
e.printStackTrace();
}
updateLabel("i is: "+i);
}
}
private void updateLabel(final String string) {
Display display=Display.getCurrent(); // display is not null...
display.asyncExec(new Runnable() { // throws NullPointerException...
@Override
public void run() {
System.out.println("test");
label.setText(string);
}
});
}
}
我不知道为什么…有人知道这可能是什么原因吗?您的
第二个线程
不是用户界面线程,因此Display.getCurrent()
将返回null
,因为只有用户界面线程具有当前显示
使用
Display.getDefault()
从任何线程获取显示。太好了!它工作!!!我可以发誓我检查了display
是否为空。。。无论如何,非常感谢。updateLabel
中的runnable还有另一个问题:在访问label.isDisposed()
之前,您应该检查标签是否仍然存在,因为它可能已被处理。
Main thread: 1
Second thread: 8
Exception in thread "Thread-0" java.lang.NullPointerException
at tst.SecondThread.updateLabel(SecondThread.java:33)
at tst.SecondThread.run(SecondThread.java:25)
at java.lang.Thread.run(Thread.java:745)