| "Widget is disposed" error with threads [message #286737] |
Thu, 16 June 2005 05:57  |
Eclipse User |
|
|
|
Hello
I wrote a small graphical editor as a subclass of FormEditor. Besides
other widgets, I placed a button on the editor which invokes some other
method A by clicking on it. In this method A another thread X is started
which parses some xml-files and invokes methods described in the
xml-files. From within this thread X a message is returned via the
Observer-pattern (i.e. with a listener). This runs fine when the editor
is openend the first time. If I close the editor, it crashes.
I tried to invoke method A with a display.asyncExec call, I then get an
error "JDI thread evaluations (Error: Exception processing async thread
queue) with the first stack trace at the end.
If I don't use display.asyncExec, the editor crashes at the time I want
to write the message returned by the listener method in a text widget
with the errors "Unhandled event loop execption" (no stacktrace) and
"Widget is disposed" with the second stacktrace at the end. If I debug
this, I see that in the method
org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:283) the widgets
display is null!
I use Eclipse 3.02 under Windows XP.
So, what is the appropriate approach to implement such a behaviour? I
assume that I misunderstood the concepts of eclipse/swt, but what?
Code snippet button creation:
btnExecute = toolkit.createButton(parent, "", SWT.FLAT);
btnExecute.setImage(NextUIPlugin.getDefault().getImageRegist ry().get(NextCore.ICON_BIG_EXEC));
btnExecute.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
Display display = btnExecute.getDisplay();
if ((display == null) || (display.isDisposed())) {
display = Display.getCurrent();
if ((display == null) || (display.isDisposed()))
display = Display.getDefault();
}
display.asyncExec(new Runnable() {
public void run() {
editor.continueAction.run();
}
});
}
});
Code snippet text widget update:
private void writeLogThreadSafe(final String logString) {
Display display = logLabel.getDisplay(); //editor.display;
if ((display == null) || (display.isDisposed())) {
display = Display.getCurrent();
if ((display == null) || (display.isDisposed()))
display = Display.getDefault();
}
display.syncExec(new Runnable() {
public void run() {
logLabel.append(lineDelimiter + logString);
}
});
}
Stack Trace 1:
java.lang.NullPointerException
at
org.eclipse.jdt.internal.debug.eval.ast.engine.ASTInstructio nCompiler.visit(ASTInstructionCompiler.java:2371)
at org.eclipse.jdt.core.dom.QualifiedName.accept0(QualifiedName .java:166)
at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2450)
at org.eclipse.jdt.core.dom.ASTNode.acceptChild(ASTNode.java:24 97)
at
org.eclipse.jdt.core.dom.ReturnStatement.accept0(ReturnState ment.java:135)
at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2450)
at org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java :2520)
at org.eclipse.jdt.core.dom.Block.accept0(Block.java:135)
at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2450)
at org.eclipse.jdt.core.dom.ASTNode.acceptChild(ASTNode.java:24 97)
at
org.eclipse.jdt.core.dom.MethodDeclaration.accept0(MethodDec laration.java:502)
at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2450)
at org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java :2520)
at
org.eclipse.jdt.core.dom.TypeDeclaration.accept0(TypeDeclara tion.java:477)
at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2450)
at org.eclipse.jdt.core.dom.ASTNode.acceptChildren(ASTNode.java :2520)
at
org.eclipse.jdt.core.dom.CompilationUnit.accept0(Compilation Unit.java:292)
at org.eclipse.jdt.core.dom.ASTNode.accept(ASTNode.java:2450)
at
org.eclipse.jdt.internal.debug.eval.ast.engine.ASTEvaluation Engine.createExpressionFromAST(ASTEvaluationEngine.java:251)
at
org.eclipse.jdt.internal.debug.eval.ast.engine.ASTEvaluation Engine.getCompiledExpression(ASTEvaluationEngine.java:156)
at
org.eclipse.jdt.internal.debug.eval.ast.engine.ASTEvaluation Engine.evaluate(ASTEvaluationEngine.java:73)
at
org.eclipse.jdt.internal.debug.ui.JavaWatchExpressionDelegat e$EvaluationRunnable.run(JavaWatchExpressionDelegate.java:14 4)
at
org.eclipse.jdt.internal.debug.core.model.JDIThread$ThreadJo b.run(JDIThread.java:2516)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:66)
Stack Trace 2:
org.eclipse.swt.SWTException: Widget is disposed
at org.eclipse.swt.SWT.error(SWT.java:2691)
at org.eclipse.swt.SWT.error(SWT.java:2616)
at org.eclipse.swt.SWT.error(SWT.java:2587)
at org.eclipse.swt.widgets.Widget.error(Widget.java:381)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:283)
at org.eclipse.swt.widgets.Text.append(Text.java:237)
at
org.next.ui.editors.WorkflowExecutionPart$4.run(WorkflowExec utionPart.java:161)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:3 5)
at
org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchr onizer.java:106)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.jav a:2750)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java :2435)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.jav a:1377)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:1348)
at
org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Work bench.java:254)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.j ava:141)
at org.eclipse.ui.internal.ide.IDEApplication.run(IDEApplicatio n.java:96)
at
org.eclipse.core.internal.runtime.PlatformActivator$1.run(Pl atformActivator.java:335)
at
org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseS tarter.java:273)
at
org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseS tarter.java:129)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.core.launcher.Main.basicRun(Main.java:183)
at org.eclipse.core.launcher.Main.run(Main.java:644)
at org.eclipse.core.launcher.Main.main(Main.java:628)
Thanks for all help and best regards
Michael
|
|
|
| Re: "Widget is disposed" error with threads [message #286739 is a reply to message #286737] |
Thu, 16 June 2005 08:54  |
Eclipse User |
|
|
|
Hi Michael,
Regardless of single or multiple threads, you cannot try to use a widget
after it has been disposed. Since you do not know when an asyncExec
runnable is going to be run, you should start it off with an isDisposed()
check if it's possible that (for example) the user has disposed the target
widget by closing its parent window. See the following snippet:
public class Main {
static int counter = 0;
public static void main (String[] args) {
Display display = new Display();
final Shell shell = new Shell(display);
shell.setBounds(10,10,200,200);
final Label label = new Label(shell, SWT.NONE);
label.setBounds(10,10,150,50);
shell.open();
new Thread(new Runnable() {
public void run() {
while (!label.isDisposed()) {
label.getDisplay().asyncExec(new Runnable() {
public void run() {
if (!label.isDisposed()) { // <------
label.setText("label text " + counter++);
}
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
}
Grant
"Michael D
|
|
|
Powered by
FUDForum. Page generated in 0.02963 seconds