从同步方法调用的Eclipse SWT:Display.syncExec()
问题描述:
我有一个自定义日志,它获取由后台线程或由用户鼠标单击事件触发的主线程打印的数据。这两个线程可能会同时在日志中打印。代码是这样的从同步方法调用的Eclipse SWT:Display.syncExec()
public void appendLine(String s, int type) {
synchronized (this) {
int index = setInputLine(s);
if (type == BG) {
updateConsole();
}
else if (type == UI) {
printConsole();
}
}
}
方法setInputLines(),updateConsole()和printConsole()作为同步没有被定义。方法updateConsole()从后台线程打印像这样
public void updateConsole() {
Display.syncExec(new Runnable() {
// update widgets UI here
});
}
但是,上述代码逻辑在测试中失败。方法appendLine()从测试后台线程中调用,并且当主线程试图通过同时调用appendLine()来获取锁时,它总是在Display.syncExec()处挂起。任何人都知道为什么?谢谢
答
Display.syncExec
将阻塞调用它的线程,直到它可以运行 - 直到下一次UI线程在主UI循环中调用Display.readAndDispatch
时才会执行此操作。
如果主UI线程在运行readAndDispatch
之前调用appendLine
,UI线程将被阻塞,等待块,然后发生死锁。
因此,从这样的同步块内调用syncExec
是不安全的。
您可能可以使用asyncExec
而不是syncExec
,因为这不会阻塞该线程。
+0
非常感谢 – CMZS
你是说'syncExec'中的代码调用'appendLine'吗? –
appendLine()正在调用updateConsole()。 updateConsole()调用Display.syncExec()。问题是,如果后台线程调用appendLine(),则主线程不能同时调用appendLine()。否则程序挂起。 – CMZS
'syncExec'是一个阻塞呼叫,如果其他人已经在呼叫它。 – nitind