2010-08-02 45 views
1

當我嘗試運行我的代碼時,我總是收到SWTException說「無效的線程訪問」。我讀了,問題似乎有代碼,試圖從UI線程外部訪問SWT對象。具體來說,我有一個表小部件,我已經添加了一個選擇監聽器。這是選擇監聽器的代碼。如何使用標準Widget工具包中的UI線程同步代碼

rosterTable.addSelectionListener(new SelectionAdapter() 

    { 
     public void widgetSelected(final SelectionEvent event) 
     { 

       createChat(connection,event); 


     } 

      }); 

,這裏是爲createChat方法的代碼:

public void createChat(final XMPPConnection connection,final SelectionEvent event) 
{ 
    Display.getDefault().syncExec(new Runnable()   
    { 
     public void run() 
     { 
      String s = event.item.toString(); 
      int length = event.item.toString().length(); 
      ClassView cv = new ClassView(connection,s.substring(11,length -1),null); 
     } 
    }); 

正如你可以看到我已經嘗試過同步的是UI線程之外的代碼,與UI線程通過包裝它在syncExec方法中,但當我選擇了表項時,我仍然得到異常,這導致我相信我已將syncExec部分放在錯誤的位置。

我也認爲這個問題可能來自這樣一個事實,即在createChat方法中實例化的ClassView對象使用SWT小部件,但我不確定。

有誰知道syncExec代碼應該放在哪裏?

或者如果我這樣做完全錯了,我該如何解決它?

更新:

我做了什麼,你說,不幸的是,我仍然得到例外,我做了一下代碼,重新設計的,所以它看起來有點不同,現在,我不認爲它應該使這裏的任何區別,但萬一是爲監聽器代碼再次:​​

rosterTable.addSelectionListener(new SelectionAdapter() 

    { 
     public void widgetSelected(final SelectionEvent event) 
     { 

      selectedUser = event.item.toString(); 
      System.out.println(selectedUser); 
      rm.createChat(selectedUser); 

     } 






    }); 

,這裏是該方法的代碼,這在現在是一個不同的類:

public void createChat(String item) 
{ 
    int length = item.length(); 
    Chatter c = new Chatter(connection,item.substring(11,length-1)); 

} 

她E公司爲異常堆棧跟蹤:

org.eclipse.swt.SWTException: Invalid thread access 
at org.eclipse.swt.SWT.error(SWT.java:3884) 
at org.eclipse.swt.SWT.error(SWT.java:3799) 
at org.eclipse.swt.SWT.error(SWT.java:3770) 
at org.eclipse.swt.widgets.Display.checkDisplay(Display.java:721) 
at org.eclipse.swt.widgets.Display.create(Display.java:783) 
at org.eclipse.swt.graphics.Device.<init>(Device.java:135) 
at org.eclipse.swt.widgets.Display.<init>(Display.java:454) 
at org.eclipse.swt.widgets.Display.<init>(Display.java:445) 
at instantmessengerplugin.ClassView.<init>(ClassView.java:33) 
at instantmessengerplugin.Chatter.<init>(Chatter.java:20) 
at instantmessengerplugin.RosterManager.createChat(RosterManager.java:48) 
at instantmessengerplugin.RosterView$1.widgetSelected(RosterView.java:103) 
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:228) 
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) 
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003) 
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3880) 
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3473) 
at instantmessengerplugin.RosterView.<init>(RosterView.java:158) 
at instantmessengerplugin.Connection.connect(Connection.java:110) 
at instantmessengerplugin.Connection$1.widgetSelected(Connection.java:65) 
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:228) 
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) 
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003) 
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3880) 
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3473) 
at instantmessengerplugin.Connection.<init>(Connection.java:77) 
at instantmessengerplugin.Connection.main(Connection.java:119) 

回答

0

我解決了這個問題。這個例外來自這樣一個事實,即在ClassView中我試圖創建一個SWT Display類的實例,當時已經有另一個實例了。該平臺只允許在任何時候打開一個平臺。

我已經改變了代碼,以便只使用一個顯示器,並且異常消失。

謝謝你的一切幫助。

0

你是從UI線程這絕對是一個問題中調用syncExec()

所有SWT事件都在UIThread上觸發,因此當您從widgetSelected()內調用createChat()時,您已經在UIThread上。在createChat()之內,然後嘗試再次阻塞UIThread,從而導致問題。

嘗試取出撥打電話syncExec()並報告發生了什麼。如果您仍然有異常,請包含堆棧跟蹤。

如果你正在創建一個簡單的SWT程序,通常你不必擔心UI線程,因爲大多數簡單的應用程序確實能夠響應事件,所以在UI線程上處理業務邏輯。當你開始產生線程時(或者使用像java.util.concurrent這樣的在幕後爲你提供線程的工作),你必須開始擔心UI線程,以便讓你的UI更具響應能力。

+0

我已經更新了包含堆棧跟蹤的問題。 – Joshy910 2010-08-03 12:33:35

+0

您顯示了createChat()的代碼,但根據堆棧跟蹤,異常事實上發生在由Chatter中的構造函數調用的ClassView構造函數中。你可以在這兩個類中發佈一些相關的代碼嗎?我們會盡快跟蹤。 – rancidfishbreath 2010-08-03 14:18:30