SWT界面在窗口跳转的时候 突然间卡死
SWTException:
Failed to execute runnable (org.eclipse.swt.SWTException: Widget is disposed)
警告: Could not open/create prefs root node SoftwareJavaSoftPrefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5. org.eclipse.swt.SWTException: Failed to execute runnable (org.eclipse.swt.SWTException: Widget is disposed) at org.eclipse.swt.SWT.error(SWT.java:4491) at org.eclipse.swt.SWT.error(SWT.java:4406) at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:138) at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:4155) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3772) at com.yc.shop.ui.LoginUI.open(LoginUI.java:89) at com.yc.shop.ui.ForgetPwdUI$8.widgetSelected(ForgetPwdUI.java:336) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:248) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4362) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1113) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4180) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3769) at com.yc.shop.ui.ForgetPwdUI.open(ForgetPwdUI.java:83) at com.yc.shop.ui.ForgetPwdUI.main(ForgetPwdUI.java:68) Caused by: org.eclipse.swt.SWTException: Widget is disposed at org.eclipse.swt.SWT.error(SWT.java:4491) at org.eclipse.swt.SWT.error(SWT.java:4406) at org.eclipse.swt.SWT.error(SWT.java:4377) at org.eclipse.swt.widgets.Widget.error(Widget.java:482) at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:354) at org.eclipse.swt.widgets.Control.setEnabled(Control.java:3319) at com.yc.shop.ui.ForgetPwdUI$6$2$1.run(ForgetPwdUI.java:256) at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35) at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:135)
一旦主动销毁shell 就
shell.dispose();
一般情况下就是 有控件还占用了shell 而shll销毁
原因
我在SWT界面使用非UI线程来访问UI线程中控件 实现 验证码倒计时 效果
非UI线程访问UI线程 是验证码倒计时
//倒计时线程
thread_time = new Thread( new Runnable() {
@Override
public void run() {
while( true ) {
try {
Thread.sleep(1000);//休眠一秒
} catch (InterruptedException e) {
e.printStackTrace();
}
//非UI线程访问UI线程
//1、Display.getDefault()
//该方法会返回用户图形界面线程中的Display实例,不管当前线程是否是用户图形界面线程,
//如果这个实例不存在,默认创建一个用户图形界面线程中的Display实例
//2、 asyncExec() 异步 线程不会被阻塞 否则 该线程同步插入UI线程造成阻塞
Display.getDefault().asyncExec(new Runnable(){
@Override
public void run() { //TOOD 非UI线程要做的事情
if( time == 0 ) { //时间归零 显示文字信息 清空验证码
button_code.setText("获取验证码");
text_code.setText("");
button_code.setEnabled( true);//解禁按钮
thread_time.stop();
return;
}
button_code.setEnabled( false);//禁用按钮 防止用户重复点击 损耗资源
button_code.setText( time-- + " S");//倒计时
}
});
}
}
});
thread_time.start();//启动线程
所以非UI线程一直依赖于Display对象
故在销毁shell之前必须先停掉线程 就可以正常使用了
thread_time.stop(); shell.dispose();
不过基于线程安全问题 使用 interrupt 来中断线程
//2、通过Thread类中成员方法interrupt(),主动退出 //正常情况通过判断标志位(interrupted()或者isInterrupted())来执行退出操作 //若遇见sleep、wait或者join阻塞状态,会抛出中断异常且清除中断状态 //此时不能通过判断标志位(interrupted()或者isInterrupted())来执行退出操作 //若需要判断,可以手动设置中断状态来执行退出操作 thread_time.interrupt();



