我只需编写SWT线程测试的测试代码,现在卡住了Display.asyncExec()奇怪的行为。
addShellListener(new ShellAdapter() {
@Override
public void shellActivated(ShellEvent e) {
Display.getDefault().asyncExec(new Runnable(){
@Override
public void run() {
for(int i=0;i<1000;i++)
{
getLabel().setText(i+"");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
});
我只是在shell start上运行带有asyncExec的循环Runnable,它每秒更新shell内的标签值,模拟计时器。一切都很好,滴答作响,直到我试图拖动窗口。窗口冻结拖动(包括&#34;滴答&#34;标签)和通知&#34;程序没有响应&#34;似乎只有Java VM进程终止才能退出。
答案 0 :(得分:0)
您为Runnable
提供的Display.asyncExec
在SWT用户界面线程中运行。如果您在此runnable中使用Thread.sleep
,则整个用户界面将在睡眠期间被阻止,因此不执行此操作。
而不是sleep
,你可以使用
Display.getDefault().timerExec(1000, runnable);
安排新的runnable在1000毫秒后运行。
答案 1 :(得分:0)
我不太确定我是否理解用例,但为了每秒更新标签,我建议生成一个后台线程,每秒触发标签更新或使用timerExec()进行更新和为下一次更新()安排另一个timerExec():
timerExec()变体
private class LabelUpdater implements Runnable {
@Override
public void run() {
if( !label.isDisposed() ) {
label.setText( ... );
label.getParent().layout();
display.timerExec( 1000, new LabelUpdater() );
}
}
}
shell.addListener( SWT.Activate, new Listener() {
@Override
public void handleEvent( Event event ) {
display.timerExec( 1000, new LabelUpdater() );
}
} );
后台主题变体
private class LabelUpdater implements Runnable {
@Override
public void run() {
if( !label.isDisposed() ) {
label.setText( ... );
label.getParent().layout();
}
}
}
Runnable runnable = new Runnable() {
@Override
public void run() {
while( !shell.isDisposed() ) {
display.asyncExec( new LabelUpdater() );
try {
Thread.sleep( 1000 );
} catch( InterruptedException ignore ) {
Thread.interrupted();
}
}
}
};
Thread thread = new Thread( runnable );
thread.setDaemon( true );
thread.start();
请注意,shell.isDisposed()
检查不是线程安全的,但在实践中并不会造成伤害,因为LabelUpdater
必须检查它更新的小部件是否仍然是活着无论如何。 (有关更详细的讨论,请参阅here。