-- 作者:jjplion
-- 发布时间:6/18/2005 12:19:00 PM
-- SWT和多线程结合使用的问题释疑
SWT和多线程结合使用的问题释疑 作者:jjp SWT作为JAVA开源世界的优秀图形库,已经得到了很多java爱好者的青睐。我最近也在使用swt开发一些应用程序。我发现多线程中使用swt需要额外的技巧。 情形: 单击一个按钮,然后新开一个线程来执行一个复杂的任务。任务执行完时,弹出一个对话框提示任务执行完毕。 示例1: package threadandui; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; public class TestSwt1 extends Shell { public static Shell shell; public static void main(String args[]) { try { Display display = Display.getDefault(); shell = new TestSwt1(display, SWT.SHELL_TRIM); shell.open(); shell.layout(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } } catch (Exception e) { e.printStackTrace(); } } public TestSwt1(Display display, int style) { super(display, style); createContents(); } protected void createContents() { setText("SWT Application1"); setSize(500, 375); final Button button = new Button(this, SWT.NONE); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { new MyThread().start(); } }); button.setBounds(80, 50, 85, 25); button.setText("start"); } protected void checkSubclass() { } class MyThread extends Thread{ public void run(){ //complex task // for(int i=0;i < 10000;i++){ // System.out.println(i); // } //display a dialog MessageBox mb = new MessageBox(shell); mb.setMessage("Task ended!"); mb.open(); } } } 该程序在单击start按钮后会有异常: Exception in thread "Thread-0" org.eclipse.swt.SWTException: Invalid thread access at org.eclipse.swt.SWT.error(SWT.java:2691) at org.eclipse.swt.SWT.error(SWT.java:2616) at org.eclipse.swt.SWT.error(SWT.java:2587) at org.eclipse.swt.widgets.Widget.error(Widget.java:381) at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:284) at org.eclipse.swt.widgets.Dialog.checkParent(Dialog.java:154) at org.eclipse.swt.widgets.Dialog.<init>(Dialog.java:116) at org.eclipse.swt.widgets.MessageBox.<init>(MessageBox.java:81) at org.eclipse.swt.widgets.MessageBox.<init>(MessageBox.java:54) at threadandui.TestSwt1$MyThread.run(TestSwt1.java:70) 为什么会有异常?没有参考书,没有人指导,你是就此罢休呢,还是刨根问底?我想知道答案,那我该怎么做呢? 请注意,swt是开源的,代码就是你最好的参考书,最好的指导老师! 查看swt源代码:at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:284) /*245*/ protected void checkWidget () { /*246*/ Display display = this.display; /*247*/ if (display == null) error (SWT.ERROR_WIDGET_DISPOSED); /*248*/ if (display.thread != Thread.currentThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS); /*249*/ if ((state & DISPOSED) != 0) error (SWT.ERROR_WIDGET_DISPOSED); /*250*/ } 第248行有判断“display.thread != Thread.currentThread ()”。显然,在我们的示例中他们是不相等的。因为,MessageBox处在新创建的线程中,而display 则处在main线程中。可见我们需要在新线程中创建一个display给MessageBox使用。“示例2”给出了答案。 示例2; /* * Created on 2005-5-26 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package threadandui; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; /** * @author jiangjunping * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class TestSwt2 extends Shell { public static Shell shell; public static void main(String args[]) { try { Display display = Display.getDefault(); shell = new TestSwt2(display, SWT.SHELL_TRIM); shell.open(); shell.layout(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } } catch (Exception e) { e.printStackTrace(); } } public TestSwt2(Display display, int style) { super(display, style); createContents(); } protected void createContents() { setText("SWT Application2"); setSize(500, 375); final Button button = new Button(this, SWT.NONE); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { new MyThread().start(); } }); button.setBounds(80, 50, 85, 25); button.setText("start"); // } protected void checkSubclass() { } class MyThread extends Thread{ public void run(){ //complex task for(int i=0;i < 50000;i++){ System.out.println(i); } //display a dialog Display display = new Display();//new display Shell shell2 = new Shell(display);//added MessageBox mb = new MessageBox(shell2);//use new display created in the current thread mb.setMessage("Task ended!"); mb.open(); display.dispose();//added } } } 好了,程序正常了!
|