2019独角兽企业重金招聘Python工程师标准>>>
final Button button = new Button(shell, SWT.CENTER);
button.setText("抓取图像");
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {final String wsdl = wsdlText.getText();final String trDate = trDateText.getText();final String flowId = flowIdText.getText();final String dest = saveText.getText();display.asyncExec(new Runnable() {public void run() {try {button.setText("处理中..");button.setEnabled(false);Main4Swt.start(wsdl, trDate, flowId, dest, bar, console);} catch (Exception e1) {console.setText(ErrorUtil.getError(e1));} finally {button.setText("抓取图像");button.setEnabled(true);}}});
}
});
我把整个button的事件处理代码都放到了display.asyncExec()中,但是运行以上代码还是会引起界面假死!这事让我抓狂
经过反复实践,得出如下实战步骤:
1. new一个Thread先
2. Thread中分三步走:
2.1 syncExec获取参数
2.2 try执行耗时操作
2.3 asyncExec处理后事
经过修改后的代码如下:
注意第一段获得参数的代码是放在syncExec中而非asyncExec final Button button = new Button(shell, SWT.CENTER);
button.setText("抓取图像");
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {new Thread() {String wsdl = null;String trDate = null;String flowId = null;String dest = null;public void run() {// [1]获取参数display.syncExec(new Runnable() {public void run() {wsdl = wsdlText.getText();trDate = trDateText.getText();flowId = flowIdText.getText();dest = saveText.getText();button.setText("处理中..");button.setEnabled(false);Swt.setLogText("");}});// [2]处理耗时操作try {Main4Swt ms = new Main4Swt();ms.start(wsdl, trDate, flowId, dest);} catch (Exception e1) {Swt.log(ErrorUtil.getError(e1), 2);}//[3]处理后事display.asyncExec(new Runnable() {public void run() {button.setText("抓取图像");button.setEnabled(true);}});}}.start();
}
});
这样做的原因是代码[2]必须在代码[1]执行完后(获得参数结束后)才能继续
最后,因为代码断[1]执行速度极快,可以将这段代码放在Thread之外,此时可以脱去syncExec的外套
最后的最后,invalid thread access的原因是你在thread中直接访问ui了组件,要么在thread之外访问,一旦在thread内访问ui, 就需要给上穿上asyncExec。
最后的最后的最后,shell也是ui,所以在thread内弹出一个对话框也要asynExec。
2013-08-24更新
在使用ProgressMonitorDialog的时候,代码要简化许多,但是参数forkable必须设置为true
ProgressMonitorDialog monitorDialog = new ProgressMonitorDialog(studio.getShell());
IRunnableWithProgress runnable = new IRunnableWithProgress() {public void run(final IProgressMonitor monitor){try{monitor.beginTask("xxxx",size);//handlemonitor.worked(1)//other UI resources except monitor should be wrapped up with asyncExecdisplay.asyncExec(new Runnable()){public void run(){MessageDialog.open(....)}}}finally{monitor.done();}}};
try {// It is recommended that fork is set to true in most cases.// If fork is set to false, the runnable will run in the UI thread// and it is the runnable's responsibility to call// Display.readAndDispatch() to ensure UI responsiveness.monitorDialog.run(true, true, runnable);
} catch (Throwable e) {Logger.error(e);
}