SWT让耗时的操作后台运行

先上段有问题的代码:
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处理后事

经过修改后的代码如下:

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();
}
});
注意第一段获得参数的代码是放在syncExec中而非asyncExec
这样做的原因是代码[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);
      //handle
      monitor.worked(1)
			
      //other UI resources except monitor should be wrapped up with asyncExec
      display.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);
}

转载于:https://my.oschina.net/uniquejava/blog/91585

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值