问题
I have an eclipse rcp application. And I have a command when this command is executing. I need to start a thread. After execution of this thread GUI must be updated. But I suppose that this thread or other non-SWT thread cannot update GUI. But it seems reasonable. When I was trying to do that I got Exception in thread "Thread-5" org.eclipse.swt.SWTException: Invalid thread access
. How I can make this goal?
回答1:
Using SWT you need to have anything that updates the GUI be done on the main thread, or in Eclipse, it's called the UI thread (it's the same thread). You are getting this error because you are trying to access an SWT object on another thread. Consider using Display.syncExec()
or Display.asyncExec()
to move the SWT related processing to the main thread. You want to be careful with syncExec()
that you don't cause a deadlock.
回答2:
Normally I would not use java.lang.Thread in an RCP application, since Eclipse provides different level of abstraction and control over long running operations via the Jobs API (https://eclipse.org/articles/Article-Concurrency/jobs-api.html). Here is a solution for your problem:
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();
回答3:
Depending on what you need to do in the background, you probably want to look at the Eclipse Jobs API which provides support for running background tasks and providing feedback to the user. Search for "eclipse jobs tutorial"; here's a good one: http://www.vogella.com/articles/EclipseJobs/article.html
回答4:
You are getting this eception, because you are trying to access UI thread from Non UI thread.
use Display.syncExec()
or Display.asyncExec()
will solve your problem.
回答5:
You're facing the most common exception in SWT world! Invalid Thread Access means only one thing: you want to modify or simply access a GUI element and you're doing it in a thread that is not the GUI thread.
It never happens when your code comes a click on button or something like this, but, when you're using background process or asynchronous notifications, it occurs all the time.
There's one solution: execute your code in a specific block:
Display.getDefautl().syncExec(new Runnable() {
public void run() {
// code related to GUI element(s)
}
}
or
Display.getDefautl().asyncExec(new Runnable() {
public void run() {
// code related to GUI element(s)
}
}
In the first case, the execution is synchronous. The calling thread waits for the run method to be executed. In the second case, the calling thread is not waiting.
To learn more about threads in Eclipse application, look at the stack in your Debug view (in debug mode). The first thread called Main is the UI thread.
回答6:
You should use Display.getDefault().asyncExec() or Display.getDefautl().syncExec().
Sample Code:
@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);
}
}
来源:https://stackoverflow.com/questions/10621554/eclipse-rcp-multithreading