2011-06-24 3 views
0

私はテーブルを持つGUIを持っています - そのテーブルはInputStreamReaderの内容によって読み込まれます。これを行うために、InputStreamを監視するスレッドを作成しています。新しい行がある場合は、それをテーブルに追加します。私が実行している問題は、スレッドの作成がアプリケーション全体をハングアップしているようだということです。これを行う典型的な方法は何ですか?SWTテーブルで、スレッドからアイテムを追加すると、ハングします

流れが行く:

GUI->ボタンonUp-> LogCatController.start-> gui.getDisplay()asyncExec(AdbThreadReader) - > addLine

public class Gui { 

    protected Shell shell; 
    private Display display; 
    private Table logCatTable; 
    private Text text; 

    private LogCatController logCatController; 
    private TableColumn tblclmnDate; 


    public void open() { 
     this.display = Display.getDefault(); 
     createContents(); 
     shell.open(); 
     shell.layout(); 
     while (!shell.isDisposed()) { 
      if (!display.readAndDispatch()) { 
       display.sleep(); 
      } 
     } 
    } 

    /** 
    * Create contents of the window. 
    */ 
    protected void createContents() { 
     ... 

     logCatTable = new Table(composite, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI); 
     FormData fd_logCatTable = new FormData(); 
     fd_logCatTable.left = new FormAttachment(0, 142); 
     fd_logCatTable.right = new FormAttachment(100); 
     fd_logCatTable.bottom = new FormAttachment(100); 
     fd_logCatTable.top = new FormAttachment(0); 
     logCatTable.setLayoutData(fd_logCatTable); 
     logCatTable.setHeaderVisible(true); 
     logCatTable.setLinesVisible(true); 

     ... 

     Button btnStart = new Button(composite_1, SWT.NONE); 
     btnStart.addMouseListener(new MouseAdapter() { 
      @Override 
      public void mouseUp(MouseEvent arg0) { 
       try { 
        logCatController.start(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
     ... 
    } 

    public Table getLogCatTable() { 
     return logCatTable; 
    } 
    public Display getDisplay() { 
     return display; 
    } 

} 


public class LogCatController { 
    private DataBindingContext m_bindingContext; 
    private static Logger logger = Logger.getLogger(AdbLine.class); 

    private LogCat logcat; 
    private Gui gui; 

    public LogCatController(Gui gui){ 
     this.gui = gui; 
     logcat = new LogCat(); 
     m_bindingContext = initDataBindings(); 
    } 

    public void start() throws IOException{ 
     logcat.execute(); 
     BufferedReader read = logcat.getSTDOUT(); 
     BufferedReader error = logcat.getSTDERR(); 

     Runnable readRunnable = new AdbLineReaderThread(read); 
     gui.getDisplay().asyncExec(readRunnable); 
    } 
private void addLine(AdbLine l){ 
    logger.debug("Adding: " + l); 
    Table logCatTable = this.gui.getLogCatTable(); 
    TableItem tableItem = new TableItem(logCatTable, SWT.NONE); 
    tableItem.setText(new String[] {"time", l.getLevel().toString(), String.valueOf(l.getPid()), l.getMessage()}); 
    tableItem.setForeground(SWTResourceManager.getColor(SWT.COLOR_CYAN)); 
} 

public class AdbLineReaderThread implements Runnable { 
    private BufferedReader read; 
    public AdbLineReaderThread(BufferedReader read){ 
     this.read = read; 
    } 

    public void run() { 
     logger.debug("AdbLinReaderThread run"); 
     String line = null; 
     try{ 
      while((line = read.readLine()) != null){ 
       logger.debug(line); 
       AdbLine l = new AdbLine(line); 
       addLine(l); 
      } 
     } catch(Exception e) { 
      System.out.println("Could not parse: " + line); 
      e.printStackTrace(); 
     } 
    } 
} 
} 


public class LogCat extends BackgroundCommand{ 

    public LogCat(){ 
     super(...);  
    }    
} 
+0

あなたのaddLine()コールはDisplay.asyncExec()にラップされ、AdbLineReaderThreadはDisplayTASKで実行されるべきではありません。SWTスレッドからすべてが発生し、SWTスレッドでGUIアップデートのみが実行されるようにします。 –

答えて

1

SWTオブジェクトのすべての操作をしなければなりません。 SWTイベントスレッドで発生します。 ...これはあなたが結果を待つ必要はありませんし、AdbLineで任意の並行性の問題を持っていない場合、代わりにあなたはasyncExec(...)を使用することができます

logCatTable.getDisplay.syncExec(new Runnable() { 
    public void run() { 
     .... 
    } 
} 

にaddLineの「肉」を囲む確実にするために

+0

はい、start()メソッドで、実行しています: "gui.getDisplay()。asyncExec(readRunnable);"これは間違っていますか? – wuntee

+0

@wuntee:いいえ、そうではありません。 readRunnableをUIスレッドで実行しています。これは、あなたのスレッドが「ぶら下がっている」のを見る理由です。あなたはSWTにUIでそれを実行するように要求しており、UIのディスパッチループが飢えています。あなたのUIはハングアップしています。あなたはバックグラウンドスレッドでそれを実行し、次にUIスレッドの更新を実行するためにnontyのアドバイスを使用します。 –

+0

それでは、updateThread(asyncExec経由で実行)とbackgroundThreadから情報を渡すために、ある種のバッファを使って新しいクラスを作成する必要がありますか?また、これが絶えず更新されている場合は、どうやってUIスレッドを飢えさせるのでしょうか? asyncExecを頻繁に「スケジュール」する必要がありますか?全体のユースケースは、決して終了しないRuntime.execコマンドのInputStreamReaderを監視しており、テーブルに出力を追加することです。 – wuntee

関連する問題