SWT和多線程結(jié)合使用的問(wèn)題釋疑
Posted on 2006-02-21 13:42 fortune 閱讀(752) 評(píng)論(0) 編輯 收藏 所屬分類: java技術(shù)SWT作為JAVA開(kāi)源世界的優(yōu)秀圖形庫(kù),已經(jīng)得到了很多java愛(ài)好者的青睞。我最近也在使用swt開(kāi)發(fā)一些應(yīng)用程序。我發(fā)現(xiàn)多線程中使用swt需要額外的技巧。
情形:
單擊一個(gè)按鈕,然后新開(kāi)一個(gè)線程來(lái)執(zhí)行一個(gè)復(fù)雜的任務(wù)。任務(wù)執(zhí)行完時(shí),彈出一個(gè)對(duì)話框提示任務(wù)執(zhí)行完畢。
示例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按鈕后會(huì)有異常:
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)
為什么會(huì)有異常?沒(méi)有參考書,沒(méi)有人指導(dǎo),你是就此罷休呢,還是刨根問(wèn)底?我想知道答案,那我該怎么做呢?
請(qǐng)注意,swt是開(kāi)源的,代碼就是你最好的參考書,最好的指導(dǎo)老師!
查看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 ()”。顯然,在我們的示例中他們是不相等的。因?yàn)椋琈essageBox處在新創(chuàng)建的線程中,而display
則處在main線程中。可見(jiàn)我們需要在新線程中創(chuàng)建一個(gè)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
}
}
}
好了,程序正常了!