`
dearwolf
  • 浏览: 344423 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

RCP中异步线程的处理

阅读更多
在RCP中要在非UI线程中执行UI线程的操作,最简单的方式就是display.syncExec或者display.asyncExec,如果UI线程所需的时间较长的话,则应该使用display.asyncExec

在执行异步线程的时候,我们一般应当继承Job或者UIJob类:UIJob是在UI线程中运行的,可以直接访问窗体组件。Job是在非UI线程中运行,如果在里面想访问窗体组件,需要通过Display.asynExec()或者synExec方式来执行。UIJob要尽量的短,不要过多的占用UI线程的时间。

在我现在的系统中,每当UI需要和Server交互的时候,都需要检测
Server是否启动,如果未启动的话,尝试启动三次,三次不成功则抛出Exception,用MessageDialog给用户提示,启动成功以后,还需载入相关信息。这样的异步线程,就只能放到Job中执行。

然而,这样还是远远不够的,试想一下,如果点完一个MenuItem以后,过了很久才会有所反应,这种用户体验岂不是糟糕透了?于是我们还要提供进度条来提高用户体验度,在RCP中,就是如下的代码:

  1. ProgressMonitorDialog progress = new ProgressMonitorDialog(null);  
  2. progress.setCancelable(true);  
  3. try {  
  4.     progress.run(truetruenew IRunnableWithProgress() {  
  5.         public void run(IProgressMonitor monitor)  
  6.                 throws InvocationTargetException {  
  7.             doSomething();  
  8.         }  
  9.     });  
  10. catch (InvocationTargetException e) {  
  11.     e.printStackTrace();  
  12. catch (InterruptedException e) {  
  13.   
  14. }  

第二行中的
progress.setCancelable(true)是为了允许客户在长时间执行后台进程的时候,可以取消掉进程的执行。这里我把实际的执行过程Extract了出来,免得方法太长,doSomething()看起来应该是这样子的:

  1. public void doSomething(IProgressMonitor monitor) {  
  2.         monitor.beginTask("Beginning...", IProgressMonitor.UNKNOWN);
  3.         monitor.subTask("Doing first job"); 
  4.         doFirstThing();
  5.         if(monitor.isCanceled()) return;
  6.         monitor.worked(1); 
  7.         monitor.subTask("Doing second job");
  8.         doSecondThing();
  9.         if(monitor.isCanceled()) return;
  10.         monitor.worked(2);
  11.         ...... 
  12.         monitor.done();  
  13.     }   
  14. }  

这样子当用户点击ProgressMonitor的Cancel按钮时,
monitor.isCanceled()就会返回true,doSomething便中止执行。

说到这里,可能就会有疑问了,monitor.isCanceled()方法只会在doFirstThing()和doSecondThing()之间才会被触发,那么如果doFirstThing()的过程中有异常情况而导致无法返回,那点击Cancel就根本没有作用啊?

唔......这个就是问题的核心所在了,我不知道别人是如何解决的,在这里我只说一下我的解决方案,希望能够起到抛砖引玉的作用:

在前面已经提到,我使用了Job来处理异步线程,然而Job是通过调用job.schedule来执行的,用户无法确保job被执行的时机以及何时结束,一般的方法是使用Listener,Observer或者某个信号量来指示Job的结束。在有些地方我用的是Observer模式,而在这种情况下,我用的是boolean变量来做指示。于是,上面的doSomething就变成了:

  1. public void doSomething(IProgressMonitor monitor) {  
  2.         monitor.beginTask("Beginning...", IProgressMonitor.UNKNOWN);
  3.         monitor.subTask("Doing first job"); 
  4.         job.schedule();
  5.         while (!jobFinished) {
  6.            if (monitor.isCanceled()) {
  7.               logger.info("monitor is canceled");
  8.               job.cancel();
  9.               return;
  10.            }
  11.            monitor.worked(times);
  12.            times++;
  13.         }
  14.         monitor.done();  
  15.     }   


这样,只要while循环没有满足结束条件,我们就可以通过点击Cancel按钮来cancel掉Job。如果job中还有些东西是无法自动cancel掉的话,比如Socket通信等,我们还可以在job.cancel()前面加上一些代码来做这样的工作,比如job.getSocket().close()等,当然还要处理好各种Exception。

在Eclipse的Article里面,有几篇分别讲述Job和ProgressMonitor的文章,很是详细,有兴趣的朋友不妨找来看看。不过文章只是讲解原理性的东西,开发中所碰到的问题,还是要靠个人的经验来分析解决......所以,还是多多coding,多多thinking,提高解决实际问题的能力吧:)
分享到:
评论
7 楼 dearwolf 2007-04-29  
嗯,你调用monitor.work(int n),就能前进了
6 楼 jzc928 2007-04-28  
设置为IProgressMonitor.UNKNOWN时
进度条只显示出来,并不前进
看了JFace代码好像JFace把IProgressMonitor.UNKNOWN的情况抛弃了
有遇到类似问题的么
5 楼 dearwolf 2007-02-13  
doFirstThing的执行过程,是无法被monitor.cancel终止的
4 楼 jianfeng008cn 2007-02-11  
doFirstThing()方法只要抛出异常不就可以实现异常向上传递了 难道这样不行?
3 楼 dearwolf 2007-01-25  
在非UI的线程里面,如果想改变UI的组件,那么就要通过获得display,然后调用display.asyncExec()来处理
2 楼 partech 2007-01-24  
引用
在RCP中要在非UI线程中执行UI线程的操作

没看明白。

RCP里面的异步执行display.asyncExec,实际上还是在UI线程中执行,只是采用了队列的形式来调度。
非UI线程是不允许修改界面元素的。我想这可能是基于同步考虑的简单实现。
1 楼 dearwolf 2007-01-17  
ProgressMonitor的Article:

http://www.eclipse.org/articles/Article-Progress-Monitors/article.html

相关推荐

    RCP部分课程

    至于性能优化,你可能需要学习如何减少内存占用、提高启动速度,以及如何合理使用线程和异步编程。 最后,课程可能还会涵盖RCP的部署策略,包括如何创建可执行的RCP应用程序、发布更新以及如何使用产品配置文件...

    rcp收集资料上传

    在实际项目中,这些操作可能会更加复杂,涉及到更多细节和优化,如异步处理、多线程、UI更新同步等问题。如果要深入学习RCP开发,还需要掌握Eclipse插件开发、SWT/JFace UI组件、模型-视图-控制器(MVC)设计模式等...

    eclipse-rcp开发培训PPT

    5. **Command Framework**:命令框架是Eclipse RCP中处理用户操作的核心机制,它将动作和UI元素解耦,使代码更易于维护和扩展。 **四、实战技巧与最佳实践** 1. **插件设计原则**:尽量保持插件小巧且专注,避免...

    swt 多线程

    在开发SWT应用程序时,尤其是在RCP(Rich Client Platform)环境中,多线程处理是常见的需求,以确保用户界面的响应性和程序的高效性。本文将深入探讨SWT中多线程的使用,特别是与UI交互相关的多线程原理。 首先,...

    mp3 manger code

    此外,为了提供良好的用户体验,可能会有线程管理的设计,比如使用SwingWorker或者ExecutorService来异步加载音乐文件和处理播放操作,避免阻塞UI主线程。 最后,考虑到软件的可扩展性和维护性,项目的代码结构应该...

    file explorer

    开发Eclipse RCP应用时,开发者还需要关注性能优化,因为资源管理器需要处理大量文件和目录,可能需要使用缓存策略和异步加载机制以提高响应速度。同时,为了保证良好的用户体验,软件应具备多线程处理能力,允许...

    SWT综合教程及安装指导

    3. 异步任务:为了执行耗时操作,通常会创建后台线程,完成后通过回调更新GUI。 三、布局管理 1. 布局(Layout):SWT提供多种布局管理器,如填充布局(FillLayout)、网格布局(GridLayout)、卡片布局...

    Java程序设计之swt教程.rar

    8. **线程与异步编程**:由于GUI操作通常需要在事件循环中执行,教程会介绍如何正确处理线程,避免阻塞用户界面,以及利用Display和Job类进行异步任务处理。 9. **示例代码**:教程中应包含丰富的代码示例,帮助...

    Java类库大全

    这个资源包包含了丰富的Java库,覆盖了从基础数据类型操作到复杂的网络通信、多线程处理、数据库操作、图形用户界面(GUI)设计等各个方面。以下是一些重要的Java类库及其相关知识点的详细解释: 1. **基础工具库**...

    J2SE进阶,java深入开发

    同时,理解如何使用JFace和RCP(Rich Client Platform)来构建更复杂的桌面应用也是必不可少的。 5. **网络编程**: 在Java中,`java.net`和`java.nio`包提供了网络通信所需的基本功能。学习TCP和UDP套接字的使用,...

    swt sqlserver分页组件

    10. **异步操作**:在Eclipse RCP环境中,通常推荐使用异步方式执行数据库查询,以避免阻塞UI线程。 通过理解并应用这些知识点,你可以创建一个功能完备的SWT SQLServer分页组件,为用户提供流畅的数据浏览体验。...

    JavaScript富应用开发

    2. **异步编程**:JavaScript是单线程的,但通过事件循环和回调函数、Promise以及async/await,开发者可以处理复杂的异步操作,提升应用性能。 3. **前端框架与库**:书中可能会涉及Angular、React或Vue.js等主流...

    hadoop rpc实例

    - **异步调用**:客户端可以选择异步方式等待结果,避免阻塞当前线程。 - **心跳机制**:保持连接活跃,减少因网络问题导致的重连次数。 ### 应用场景 Hadoop RPC广泛应用于Hadoop生态系统中的各种组件,如HDFS的...

    eclipse rap教程

    - **性能优化技巧**:包括减少HTTP请求、压缩资源、异步处理等方法。 - **错误处理与日志记录**:理解和实施有效的错误处理策略,以及使用日志记录工具进行问题排查。 通过这个Eclipse RAP教程,你可以逐步掌握...

    eclipse-jetty-plugin-master_源码.rar

    3. **Servlet容器实现**:源码揭示了Jetty作为Servlet容器的内部实现,包括请求和响应处理、Servlet的加载和管理、线程模型以及会话管理等核心功能。这有助于深入理解Servlet容器的工作机制。 4. **WebSocket支持**...

    ReCapProject

    C#的多线程和异步处理能力可以帮助ReCapProject API更高效地运行。通过合理设计并发策略,可以显著提升数据处理速度,尤其是在处理大型项目时。 七、应用程序集成与部署 最后,我们需要将开发的功能整合成一个完整...

    基于android平台的视频播放器设计说明.doc

    开发者需要掌握如何使用MediaPlayer加载、播放、控制视频流,并处理播放过程中的错误。同时,考虑到用户界面,可能需要使用SurfaceView或TextureView来显示视频画面,并结合MediaController实现播放控制条。 此外,...

Global site tag (gtag.js) - Google Analytics