如何在一个单独的线程完成之前禁用 SWT selectionListener

Posted

技术标签:

【中文标题】如何在一个单独的线程完成之前禁用 SWT selectionListener【英文标题】:How to disable an SWT selectionListener until a separate thread has been completed 【发布时间】:2017-03-11 19:55:36 【问题描述】:

我有一个带有 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();
        
    


【问题讨论】:

如果您认为某个答案解决了问题,请单击绿色复选标记将其标记为“已接受”。这有助于将注意力集中在仍然没有答案的旧帖子上。 【参考方案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() 安排给定的可运行文件“在下一个合理的机会”在 UI 线程上执行。

另请注意,在调用 runnable 时,具有 的小部件可能已被处理掉。因此,在访问小部件之前,有必要在 runnable 内部检查这种情况。

【讨论】:

【参考方案2】:

与其纠结是否启用了侦听器,您可以只跟踪您启动的线程,而不是在前一个线程完成之前启动另一个线程。

见Thread.isAlive()

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();
            
        
    

【讨论】:

以上是关于如何在一个单独的线程完成之前禁用 SWT selectionListener的主要内容,如果未能解决你的问题,请参考以下文章

在 SWT 中禁用组件选择

在工作线程完成 MFC 时禁用控制变量

如何在单独的线程中处理套接字请求,线程似乎阻塞了主进程

如何从 Java 中的另一个线程更新 SWT GUI

SWT 如何有效地从 SelectionListener 访问其他控件

java 计算器SWT/RAP(版本3)键盘鼠标兼容