SWT表,从线程添加项目挂起

时间:2011-06-24 15:58:50

标签: multithreading swt

我有一个带表的GUI - 该表由InputStreamReader的内容填充。为了做到这一点,我正在创建一个监视InputStream的线程,当有一个新行要读取时,它会将它添加到表中。我遇到的问题是线程的创建似乎挂起了整个应用程序。这种做法的典型方式是什么?

流程如下:

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(...);     
    }               
}

1 个答案:

答案 0 :(得分:1)

SWT对象的所有操作必须在SWT事件线程中进行。为了确保这包含addLine的“肉”

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

或者,如果您不需要等待结果并且asyncExec(...)没有任何并发​​问题,则可以使用AdbLine ...