2009-04-16 143 views
0

我一直在問最近一個項目的許多問題。這裏是我所處的場景,任何幫助或正確的方向將有助於很多...EDT與主線程之間的通信

這是一個使用服務器和多個客戶端構建的網絡程序。每個客戶端都有一個GUI,它必須根據服務器發送的命令行事。每個客戶都被包裝在名爲Player的類中。這個Player有一個GUI(擴展JFrame)和一個主要方法,並且服務器只有一個主要方法(沒有GUI)。起初,這個類在主線程中創建這樣的:

EventQueue.invokeLater(new Runnable() 
{ 
    public void run() 
    { 
     new Player().setVisible(true); 
    } 
}); 

這是工作的罰款,直到我意識到整個Player類在EDT現在正執行。因此,當我等待來自服務器的命令時,整個GUI將鎖定,直到發送該命令並執行適當的操作。正如你可以想象的那樣,這是一個可怕的設計,並且被證明是編碼環境的一個真正的痛苦,當你每次想要檢查某些東西時都必須找到一些瘋狂的工作,這樣GUI才能保持完好無損。

很顯然,我必須在單獨的線程中檢查來自服務器的命令,並在EDT中運行GUI組件。我的第二個實現有兩個類 - 一個用於GUI,另一個用於Player。當時的想法是,該Player有這樣舉行的GUI,這樣我可以從Player類訪問GUI的變量,像這樣:

class Player 
{ 
    public GUI gui; 

    ... 

    // And then start this gui inside of the EDT. 
    EventQueue.invokeLater(new Runnable() 
    { 
     public void run() 
     { 
       this.gui = new GUI().setVisible(true); 
     } 
    } 

這也不管用,新Runnablethis因爲裏面對象是指Runnable對象,而不是Player

如何在一個線程中的Player類與EDT線程中相應的GUI類之間進行通信?

回答

0

而不是使用匿名內部類,爲什麼不只是聲明一個類的實現Runnable,並有一個構造函數將GUI實例作爲參數?

此外,如果您的GUI類不是線程安全的,請考慮使用消息隊列在EDT &主線程之間進行通信。

3

來處理與this指針你的問題,你應該寫:

class Player 
{ 
    public GUI gui; 

    ... 

    // And then start this gui inside of the EDT. 
    EventQueue.invokeLater(new Runnable() 
    { 
     public void run() 
     { 
       Playser.this.gui = new GUI().setVisible(true); 
     } 
    } 
} 
1

你可以試試這個:

類球員 { public GUI gui;

... 

// And then start this gui inside of the EDT. 
EventQueue.invokeLater(new Runnable() 
{ 
    public void run() 
    { 
      Player.this.gui = new GUI().setVisible(true); 
    } 
} 
2

鮑里斯·帕夫洛維奇得到語法正確的(實際上,你可以只取出this.),但仍是代碼沒有意義。 字段在Runnable事件排隊後的某個時間被初始化,所以播放器線程使用它是不安全的。

您可以在EDT上構建Player(但在EDT上執行網絡操作)。或者將GUI註冊爲Player的監聽器(觀察者)。 invokeAndWait可以工作,但是很危險,因爲它經常導致偶爾難以調試的死鎖。

1

「直到我意識到整個玩家類在EDT現在正執行」

發生在美國東部時間,但要求這個類可能不是方法的構造函數。

您應該按照最初的設計構建播放器GUI。

EventQueue.invokeLater(new Runnable() 
{ 
    public void run() 
    { 
     new Player().setVisible(true); 
    } 
}); 

但玩家可以在構造函數中啓動一個單獨的線程(我個人會在玩家之間共享一個連接)。

當然,修改可見組件時,服務器的回調方法應該使用invokeLater()。