我有一个带有GUI线程和SQL线程的应用程序。 GUI中显示了一个树,单击树中的项目将启动一个单独的线程,该线程将启动SQL查询。查询完成后,树会更新。
问题是,如果用户在获取线程完成之前再次单击树,则树将在有机会完成获取数据之前更新,并且树将被错误地更新。有没有办法在启动另一个线程之前禁用侦听器,然后在线程完成后重新启用它以防止虚假查询?
private SelectionListener getTreeListener()
{
//main tree listener that populates folder and report objects on the left side of the SashForm
SelectionListener l = new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent arg0)
{
Thread runThread = new FetchTreeChildrenThread(_es,_mgr,_PAI,_PE,_SelectedPub,Selected_Tree_Item);
runThread.start();
}
}
}
答案 0 :(得分:1)
获取代码需要提供在查询完成后从“SQL线程”中调用的回调。
然后,UI代码可以注册这样的回调,以在执行查询后重新启用树。
例如(在widgetSelected
方法中):
Display display = new Display();
Runnable uiUpdateCode = new Runnable() {
@Override
public void run() {
if( !tree.isDisposed() ) {
// re-attach selection listner
}
}
};
Runnable doneCallback = new Runnable() {
@Override
public void run() {
if( !display.isDisposed() ) {
display.asyncExec( uiUpdateCode );
}
}
};
Thread backgroundThread = new Thread( new Runnable() {
@Override
public void run() {
// ... execute query
doneCallback.run();
}
} );
backgroundThread.start();
请注意,SWT仅允许在UI线程上执行的代码来操作窗口小部件。因此,display.asyncExec()
会调度给定的runnable在下一个合理的机会'在UI线程上执行'。
另请注意,在调用runnable时,可能已经处理掉了可能的小部件。因此,在访问窗口小部件之前,有必要在runnable中检查这种情况。
答案 1 :(得分:0)
不管是否启用了侦听器,您都可以跟踪您启动的线程,而不是在上一个完成之前启动另一个线程。
private SelectionListener getTreeListener()
{
//main tree listener that populates folder and report objects on the left side of the SashForm
SelectionListener l = new SelectionAdapter()
{
private Thread runThread;
@Override
public void widgetSelected(SelectionEvent arg0)
{
if (runThread == null || (!runThread.isAlive()))
{
runThread = new FetchTreeChildrenThread(_es,_mgr,_PAI,_PE,_SelectedPub,Selected_Tree_Item);
runThread.start();
}
}
}
}