Recently, I've faced with SWTException error when was trying to insert a new TableItem into the SWT Table from another thread. Reading java doc about TableItem class I found out, that with creation a new instance of this class, SWTException may occurred:
Throws SWTException: if not called from the thread that created the parent
It means that I can't create a TableItem instance in the thread which is distinct from that one, in which Table was created.
I wrote a simple program to reproduce my problem: it's a window with one button and with a table which has a single column. When pressing the button a new thread is started. In this thread there's a cycle in which 5 table items are created with timed out = 1 sec.
Here's a code snippet, which represents a first attempt:
private class StartServerListener extends SelectionAdapter {
@Override
public void widgetSelected(final SelectionEvent e) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
addItemsToTable();
}
});
}
}
private void addItemsToTable() {
TableViewer tableViewer = simpleGui.getTableViewer();
for (int i = 0; i < 5; i++) {
TableItem tableItem = new TableItem(tableViewer.getTable(), SWT.NONE);
String itemText = "Item #" + i + " was created.";
tableItem.setText(itemText);
logger.info(itemText);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
logger.error("Current thread has been interrupted by another one: {}", e);
}
}
}
After running the program and pressing 'Start Server' button we have the following output:
Exception in thread "AWT-EventQueue-0" org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.SWT.error(Unknown Source)
at org.eclipse.swt.widgets.Widget.error(Unknown Source)
at org.eclipse.swt.widgets.Widget.checkWidget(Unknown Source)
at org.eclipse.swt.widgets.Table.getItemCount(Unknown Source)
at org.eclipse.swt.widgets.TableItem.<init>(Unknown Source)
at com.rusya7.SimpleGuiController.addItemsToTable(SimpleGuiController.java:47)
at com.rusya7.SimpleGuiController.access$0(SimpleGuiController.java:43)
at com.rusya7.SimpleGuiController$StartServerListener$1.run(SimpleGuiController.java:30)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:641)
at java.awt.EventQueue.access$000(EventQueue.java:84)
at java.awt.EventQueue$1.run(EventQueue.java:602)
at java.awt.EventQueue$1.run(EventQueue.java:600)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:611)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Reading SWT documentation I found the solution: replace EventQueue.invokeLater(...) call to Display.getDefault().asyncExec(...). Let's modify the above snippet:
@Override
public void widgetSelected(final SelectionEvent e) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
addItemsToTable();
}
});
}
}
private void addItemsToTable() {
TableViewer tableViewer = simpleGui.getTableViewer();
for (int i = 0; i < 5; i++) {
TableItem tableItem = new TableItem(tableViewer.getTable(), SWT.NONE);
String itemText = "Item #" + i + " was created.";
tableItem.setText(itemText);
logger.info(itemText);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
logger.error("Current thread has been interrupted by another one: {}", e);
}
}
}
After running the program and pressing 'Start Server' button we have the following output:
[14 Nov 2011 16:07:44:049][15][Launcher][INFO]: Log4j configuration was successfully loaded.
[14 Nov 2011 16:07:46:318][49][SimpleGuiController][INFO]: Item #0 was created.
[14 Nov 2011 16:07:47:319][49][SimpleGuiController][INFO]: Item #1 was created.
[14 Nov 2011 16:07:48:320][49][SimpleGuiController][INFO]: Item #2 was created.
[14 Nov 2011 16:07:49:320][49][SimpleGuiController][INFO]: Item #3 was created.
[14 Nov 2011 16:07:50:321][49][SimpleGuiController][INFO]: Item #4 was created.
The full code you can find here: swt-widget-thread-problem
Good site for searching java libs: http://grepcode.com/
No comments:
Post a Comment