`

解决SWT中事件响应的线程冲突问题

阅读更多
最近工作中要做一件这样的事情,就是在一个已有的SWT界面上对一些业务层写好的事件做响应,也就是是SWT的组件订阅了某个时间Listener,当事件触发的时候响应的SWT组件会做出一些信息的显示工作。一开始我们的程序是这样写的:我们所期待的那样做出了反应。问题解决了。总结一下也就是 SWT的在对其组件进行操作的时候有一个单线程的约束,直接的赋值方式是行不通的,SWT在*.widget.Display类中提供了两个方法可以间接的在非用户线程的进行图形构件的访问操作,这是通过的syncExec(Runnable)和asyncExec(Runnable)这两个方法去实现的。而方法syncExec()和asyncExec()的区别在于前者要在指定的线程执行结束后才返回,而后者则无论指定的线程是否执行都会立即返回到当前线程。
我们会在一个业务的监听器中将我们需要进行设置(重绘)的SWT组件从其构造函数中传过去:

java 代码
 
  1. ServiceListener serviceListener = new ServiceListener(txtInformation);  


这里做下说明,ServiceListener是我们自己实现的一个实现了javax.management.NotificationListener 接口的Listener ,它必须实现其handleNotification方法,而txtInformation是一个swt.Text的组件。我们想当然的在这个方法中做一些跟SWT有关的操作于是我们将这个Text组件传进去,再在响应事件中对其进行操作。

java 代码
 
  1. public class ServiceListener implements NotificationListener {  
  2.   
  3. public ServiceListener(Text information) {  
  4. // TODO Auto-generated constructor stub  
  5. super();  
  6. txtInformation = information;  
  7. }  
  8.   
  9. Text txtInformation;  
  10.   
  11. public void handleNotification(Notification notification, Object handback) {  
  12.   
  13. ... ....  
  14.   
  15. //比如说我们取到某些值想要把它赋值给我们的SWT组件  
  16.   
  17. String result = "this is a test!";  
  18.   
  19. txtInformation = result;  
  20.   
  21. }  
  22.   
  23. }  


我们期待的是,当我们期待的事件发生后,会触发这个响应事件做出响应,而我们在已有的SWT界面上的TEXT组件的值会发生改变。但事实上事件是触发了,但程序走到 “txtInformation.setText(result); ”这一行的时候无端停住了,并报了个异常。单我们但不跟踪并查看SWT的源代码的时候看到Text组件中的setText方法是这样写的:
java 代码
 
  1. public void setText (String string) { 

  2. checkWidget (); 

  3. if (string == null) error (SWT.ERROR_NULL_ARGUMENT); 

  4. string = Display.withCrLf (string); 

  5. if (hooks (SWT.Verify) || filters (SWT.Verify)) { 

  6. int length = OS.GetWindowTextLength (handle); 

  7. string = verifyText (string, 0, length, null); 

  8. if (string == nullreturn

  9. }  
  10. TCHAR buffer = new TCHAR (getCodePage (), string, true); 

  11. OS.SetWindowText (handle, buffer);  
  12. /* 
  13. * Bug in Windows.  When the widget is multi line 
  14. * text widget, it does not send a WM_COMMAND with 
  15. * control code EN_CHANGE from SetWindowText () to 
  16. * notify the application that the text has changed. 
  17. * The fix is to send the event. 
  18. */  
  19. if ((style & SWT.MULTI) != 0) { 

  20. sendEvent (SWT.Modify);  
  21. // widget could be disposed at this point 



  22. }  


其中checkWidget ();方法引起了我们的注意,进去看看:
java 代码
 
  1. /** 
  2. * Throws an SWTException if the receiver can not 
  3. * be accessed by the caller. This may include both checks on 
  4. * the state of the receiver and more generally on the entire 
  5. * execution context. This method should be called by 
  6. * widget implementors to enforce the standard SWT invariants. 
  7. * 
  8.  
  9. * Currently, it is an error to invoke any method (other than 
  10. isDisposed()) on a widget that has had its 
  11. dispose() method called. It is also an error 
  12. * to call widget methods from any thread that is different 
  13. * from the thread that created the widget. 
  14. * 
  15.  
  16. * In future releases of SWT, there may be more or fewer error 
  17. * checks and exceptions may be thrown for different reasons. 
  18. * 
  19.  
  20. * 
  21. * @exception SWTException 
    •   * 
    •     
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    •  
    • * 
    •     
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    •  
    • *
     
  22. */  
  23. protected void checkWidget () { 

  24. Display display = this.display; 

  25. if (display == null) error (SWT.ERROR_WIDGET_DISPOSED); 

  26. if (display.thread != Thread.currentThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
  27.   
  28. if ((state & DISPOSED) != 0) error (SWT.ERROR_WIDGET_DISPOSED); 

  29. }  

看见没有,事实上这里明显的是不能在多个线程中对同一个SWT组件进行操作,从ibm developerworks上了解到:Java语言本身就提供了多线程机制,这种机制对GUI编程来说是不利的,它不能保证图形构件操作的同步与串行化。SWT采用了一种简单而直接的方式去适应本地GUI系统对线程的要求:在SWT中,通常存在一个被称为"用户线程"的唯一线程,只有在这个线程中才能调用对构件或某些图形API的访问操作。如果在非用户线程中程序直接调用这些访问操作,那么SWTExcepiton异常会被抛出。

那么怎么解决这个问题了,按照developerworks提出的方案,我们对我们的之前写的程序稍微做了一些改进:


java 代码
 
  1. public class ServiceListener implements NotificationListener {  
  2.   
  3. public ServiceListener(Text information) {  
  4. // TODO Auto-generated constructor stub  
  5. super();  
  6. txtInformation = information;  
  7. }  
  8.   
  9. Text txtInformation;  
  10.   
  11. public void handleNotification(Notification notification, Object handback) {  
  12.   
  13. ... ....  
  14.   
  15. //比如说我们取到某些值想要把它赋值给我们的SWT组件  
  16.   
  17. String result = "this is a test!";  
  18.   
  19. //以下是新加的:  
  20.   
  21. txtInformation.getDisplay().asyncExec(new Runnable() {  
  22.   
  23. public void run() {  
  24. txtInformation.setText(result);  
  25. }  
  26. });  
  27.   
  28. }  
  29.   
  30. }  

很好程序如我们所期待的那样做出了反应。问题解决了。总结一下也就是 SWT的在对其组件进行操作的时候有一个单线程的约束,直接的赋值方式是行不通的,SWT在*.widget.Display类中提供了两个方法可以间接 的在非用户线程的进行图形构件的访问操作,这是通过的syncExec(Runnable)和asyncExec(Runnable)这两个方法去实现 的。而方法syncExec()和asyncExec()的区别在于前者要在指定的线程执行结束后才返回,而后者则无论指定的线程是否执行都会立即返回到 当前线程。

enjoying!
分享到:
评论
1 楼 owennet 2008-04-21  
很好,很实在!!

相关推荐

    swt线程冲突与解决

    本文将详细探讨SWT中的线程冲突问题及其解决方案。 #### SWT线程冲突的原理 SWT库设计之初就考虑到了性能和资源管理的问题,因此它采用了单线程模型来处理所有与UI相关的事件。这意味着所有对SWT组件的操作(包括...

    局域网聊天 SWT Java 多线程问题已经解决

    本主题将深入探讨如何利用SWT(Standard Widget Toolkit)和Java来构建一个局域网内的聊天应用,并解决其中涉及的多线程问题。SWT是Eclipse基金会提供的一个开源GUI库,它为Java开发者提供了与操作系统更紧密集成的...

    SWT并发例子(后台耗时线程)

    在SWT中,我们可以使用`Display.asyncExec`或`Display.syncExec`方法来在事件调度线程中执行代码,而使用`new Thread()`来创建并启动新的后台线程来执行耗时任务。以下是一个基本的示例: ```java Button button = ...

    swt页面后台多线程接受ModBUS协议Socket通讯的数据

    在SWT中创建GUI时,我们可以利用事件驱动模型,用户界面元素的交互会触发事件处理器。 2. **MODBUS协议**:ModBUS是一种简单但功能强大的串行通信协议,广泛应用于工业自动化领域。它定义了数据如何在主设备(如PLC...

    swt 多线程

    本文将深入探讨SWT中多线程的使用,特别是与UI交互相关的多线程原理。 首先,我们需要理解UI线程,也称为事件调度线程或AWT/SWT线程,它负责处理所有的用户界面更新和事件处理。在SWT中,所有的GUI操作必须在UI线程...

    SWT内存泄露解决办法

    SWT(Standard Widget Toolkit)是...总结来说,解决SWT内存泄露问题需要理解内存管理的基本原理,正确使用SWT API,并配合合适的检测工具进行诊断。只有这样,才能确保SWT应用在长期运行中保持良好的性能和稳定性。

    swt资源释放问题

    但是, SWT 中的资源释放问题是一件棘手的事情。如果不正确地释放资源,可能会导致内存泄露、程序崩溃等问题。下面,我们将详细介绍 SWT 中的资源释放问题。 一、Display 实例的创建和释放 在 SWT 中,Display ...

    SWT事件一览表

    SWT事件处理机制是其核心特性之一,它允许开发者响应各种用户交互行为,从而实现动态和响应式的界面设计。 ### SWT事件类型及处理 #### ControlEvent:控件事件 - **监听器和适配器**:`ControlListener`和`...

    SWT JFace 按键、事件、监听

    本文将详细介绍SWT中的按键及其对应的常量表、`KeyEvent`事件和`VerifyEvent`事件的相关知识,并通过示例进行说明。 #### 按键与对应的常量表 SWT定义了一系列的常量来表示不同的按键,这些常量通常用于按键事件的...

    SWT_AWT_Swing事件处理机制

    在Java编程语言中,SWT(Standard Widget Toolkit)、AWT(Abstract Window Toolkit)和Swing是用于构建图形用户界面(GUI)...同时,对源码的探索也有助于开发者深入理解Java GUI编程的底层原理,提高解决问题的能力。

    解决SWT原生库找不到的问题

    ### 解决SWT原生库找不到的问题 #### SWT简介与问题背景 SWT(Standard Widget Toolkit)是一款开源的图形用户界面工具包,主要用于构建Java应用的用户界面。它由IBM开发并维护,提供了丰富的控件集,允许开发者...

    SWT中文教程.rar

    SWT拥有活跃的社区和丰富的在线资源,如Eclipse官方文档、Stack Overflow上的问答,以及各种教程和博客文章,可以帮助开发者解决问题和学习新技能。 通过这个SWT中文教程,无论是初学者还是有一定经验的开发者,都...

    swt事件处理的编码实现

    在SWT中,我们可以通过实现`MouseListener`接口来监听鼠标事件。`MouseListener`接口包含三个方法:`mouseDown()`, `mouseUp()`, 和 `mouseDoubleClick()`。在这个例子中,我们关心的是`mouseDoubleClick()`方法。...

    SWT源码 swt.jar

    源代码可以被导入到任何支持Java开发的IDE,比如Eclipse,通过关联源码,可以在编写代码时直接查看SWT的内部实现,有助于理解和解决问题。 SWT的主要特点包括: 1. 原生外观:SWT控件是基于操作系统提供的控件,...

    swt-64.rar_64位swt_64的SWT_SWT64_swt.jar 64位_swt64位

    SWT(Standard Widget Toolkit)是Java编程环境中一个用于创建图形用户界面(GUI)的开源库,它是Eclipse项目的一部分。标题“swt-64.rar_64位swt_64的SWT_SWT64_swt.jar 64位_swt64位”表明这个压缩包包含了适用于...

    Java中的线程详细介绍 DOC版

    在SWT中,UI线程是创建`Display`的线程,负责处理所有的用户界面更新。例如,以下代码展示了如何创建一个简单的SWT应用程序: ```java public static void main(String[] args) { Display display = new Display()...

    swt源码以及jar

    首先,源码部分允许开发者深入理解SWT的工作原理,探究其内部结构,这对于进行定制化开发或者解决特定问题时非常有用。通过查看源代码,我们可以学习到如何利用SWT创建窗口、控件、布局管理等,以及如何处理事件和...

    SWT插件中文教程SWT常用方法

    SWT(Standard Widget Toolkit)是Java编程环境中用于创建图形用户界面(GUI)的一种开源库,它是Eclipse项目的一部分。SWT提供了与操作系统本机UI组件的直接交互,从而能够创建性能高效、外观与操作系统的原生应用...

    SWT 中嵌入Word 控件应用

    6. **事件处理**:集成Word控件后,可能需要监听并响应用户的操作,如文档加载完成、保存事件、关闭事件等。 7. **错误处理**:由于是跨进程通信,可能会遇到异常或错误,需要编写适当的错误处理代码来确保程序的...

Global site tag (gtag.js) - Google Analytics