2012-05-16 3 views
3

У меня есть приложение eclipse rcp. И у меня есть команда, когда эта команда выполняется. Мне нужно начать поток. После выполнения этого потока GUI должен быть обновлен. Но я полагаю, что этот поток или другой поток не-SWT не может обновить GUI. Но это кажется разумным. Когда я пытался это сделать, я получил Exception in thread "Thread-5" org.eclipse.swt.SWTException: Invalid thread access. Как я могу сделать эту задачу?Eclipse RCP многопоточность

ответ

5

С помощью SWT вам необходимо иметь что-либо, что обновляет графический интерфейс в основном потоке, или в Eclipse, это называется потоком пользовательского интерфейса (это тот же поток). Вы получаете эту ошибку, потому что пытаетесь получить доступ к SWT-объекту в другом потоке. Рассмотрите возможность использования Display.syncExec() или Display.asyncExec(), чтобы переместить обработку, связанную с SWT, в основную нить. Вы хотите быть осторожным с syncExec(), что вы не вызываете тупик.

+0

Да! «Вы получаете эту ошибку, потому что пытаетесь получить доступ к SWT-объекту в другом потоке». Это то, что я сказал в своем посте. Можете ли вы подробно объяснить, что такое Display.syncExec() или Display.asyncExec() и как их использовать в Eclipse RCP? – itun

+0

Вы можете посмотреть Javadoc для них или Google, есть много примеров. Они в основном запускают код в потоке пользовательского интерфейса, чтобы вы могли получить доступ к объектам SWT. –

1

В зависимости от того, что вам нужно сделать в фоновом режиме, вы, вероятно, захотите ознакомиться с API-интерфейсом Eclipse Jobs, который обеспечивает поддержку для запуска фоновых задач и предоставления обратной связи пользователю. Найдите «учебник по работе с eclipse»; вот хороший: http://www.vogella.com/articles/EclipseJobs/article.html

1

Вы получаете это переключение, потому что вы пытаетесь получить доступ к потоку пользовательского интерфейса из потока без UI. использование Display.syncExec() или Display.asyncExec() решит вашу проблему.

0

Вы столкнулись с самым распространенным исключением в мире SWT! Недопустимый доступ к потоку означает только одно: вы хотите изменить или просто получить доступ к элементу GUI, и вы делаете это в потоке, который не является потоком графического интерфейса пользователя.

Это никогда не происходит, когда ваш код нажимает кнопку или что-то в этом роде, но при использовании фонового процесса или асинхронных уведомлений это происходит постоянно.

Там одно решение: выполнить свой код в определенном блоке:

Display.getDefautl().syncExec(new Runnable() { 
    public void run() { 
     // code related to GUI element(s) 
    } 
} 

или

Display.getDefautl().asyncExec(new Runnable() { 
    public void run() { 
     // code related to GUI element(s) 
    } 
} 

В первом случае выполнение синхронно. Вызывающий поток ожидает выполнения метода выполнения. Во втором случае вызывающий поток не ждет.

Чтобы узнать больше о потоках в приложении Eclipse, посмотрите на стек в режиме отладки (в режиме отладки). Первый поток под названием Main - это поток пользовательского интерфейса.

0

Вы должны использовать Display.getDefault(). AsyncExec() или Display.getDefautl(). SyncExec().

Пример код:

@PostConstruct 
public void createControls(Composite parent) { 
    .... \\ label definition 
} 
public void updateInterface(String message) 
    { 
     try{ 
      Display.getDefault().asyncExec(new Runnable() { 
       @Override 
       public void run() { 
       try{ 
         label.setText(message); 
        } 
        catch(Exception exc){ 
         System.out.println(exc); 
        }    
       } 
      }); 
     } 
     catch(Exception exception){ 
      System.out.println(exception); 
     } 
    } 
1

Обычно я бы не стал использовать java.lang.Thread в RCP приложения, так как Eclipse, обеспечивает различный уровень абстракции и контроля за длительные операции через API Jobs (https://eclipse.org/articles/Article-Concurrency/jobs-api.html). Вот решение вашей проблемы:

Runnable uiUpdater = new Runnable() { 
     public void run() { 
      // update SWT UI safely here 
      // ... 
     } 
    }; 
    Job longRunningOperation = new Job("My command") { 
     protected IStatus run(IProgressMonitor monitor) { 
      // some time consuming code here   
      // ...  
      Display.getDefault().asyncExec(uiUpdater); 
      return Status.OK_STATUS; 
     } 
    }; 
    longRunningOperation.schedule();