swt 界面假死 使用asyncExec(runnable),没出现多线程的效果

问题描述

我现在做网络抓取数据包后再还原成html的一个实验,使用swt实现界面,点击开始按钮开始抓包,点击停止按钮停止抓包,想法是抓取到一个数据包就在表格显示,也就是动态刷新界面,当抓取的数据包上千上万的时候界面就假死了,要停止抓包根本停止不了,有时候只有点击鼠标界面就出现无法响应的情况。整个界面代码如下,现在做一个小实验,点击开始按钮,表格创建1000行,第一列为名称,第二列为进度条。但是我想在1000行生成之前停止,但是1000行没生成完之前stop根本不好使,在1000行生成完之后点stop才能停止进度条。哪位大侠,帮忙修改一下吧import org.eclipse.swt.SWT;import org.eclipse.swt.custom.TableEditor;import org.eclipse.swt.events.SelectionAdapter;import org.eclipse.swt.events.SelectionEvent;import org.eclipse.swt.layout.GridData;import org.eclipse.swt.layout.GridLayout;import org.eclipse.swt.widgets.Button;import org.eclipse.swt.widgets.Display;import org.eclipse.swt.widgets.ProgressBar;import org.eclipse.swt.widgets.TableItem;import org.eclipse.swt.widgets.Shell;import org.eclipse.swt.widgets.Table;import org.eclipse.swt.widgets.TableColumn;public class MutiTaskGUI { private Shell shell = null; private Table table = null; public MutiTaskGUI( ){ //构造方法中调用初始化窗口的方法 init(); } //初始化窗口方法 public void init() { shell = new Shell(); shell.setSize(282, 240); shell.setLayout(new GridLayout()); shell.setText("多线程"); Button bt = new Button ( shell , SWT.NONE); bt.setText("开始一个任务"); //停止线程 Button stop = new Button(shell, SWT.NONE); stop.setText("stop"); table = new Table(shell, SWT.BORDER); table.setLayoutData( new GridData(SWT.FILL,SWT.FILL,true,true)); table.setHeaderVisible(true); table.setLinesVisible(true); String[] header = new String[]{"任务","进度","操作"}; // 创建表头 for (int i = 0; i < 3; i++) { TableColumn col = new TableColumn(table, SWT.NONE); col.setText( header[i] ); } //设置表头宽度 table.getColumn(0).setWidth(80); table.getColumn(1).setWidth(150); table.getColumn(2).setWidth(80); shell.pack(); //注册创建任务按钮事件 bt.addSelectionListener( new SelectionAdapter(){ //当单击创建一个任务按钮时 public void widgetSelected(SelectionEvent e) { //首先创建一个Task对象 for(int i = 0 ; i < 1000; i++){ Task task = new Task(); //然后在表格中添加一行 task.createTableItem(table); //最后启动该任务,该任务为一个线程 task.start(); } } }); stop.addSelectionListener(new SelectionAdapter() { @Overridepublic void widgetSelected(SelectionEvent arg0) {// TODO Auto-generated method stubTask.setDone(true);}}); } //获得和设置属性的getter和setter方法 public Shell getShell() { return shell; } public void setShell(Shell shell) { this.shell = shell; } public Table getTable() { return table; } public void setTable(Table table) { this.table = table; } public static void main(String[] args) { Display display = Display.getDefault(); MutiTaskGUI mutiTask= new MutiTaskGUI(); mutiTask.getShell().open(); while (!mutiTask.getShell().isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } }}class Task extends Thread { //该类的一些属性 private Table table = null; //是否停止的标志 public static boolean done = false; //声明进度条对象 private ProgressBar bar = null; private int min = 0; private int max = 100; int i = 0; //创建表格中的一行 public void createTableItem(Table table) { done = false; TableItem item = new TableItem(table, SWT.NONE); item.setText(this.getName()); // item.setText(new String[]{k +"",i+2+""}); // 创建一个进度条 bar = new ProgressBar(table, SWT.NONE); bar.setMinimum(min); bar.setMaximum(max); // 创建一个可编辑的表格对象 TableEditor editor = new TableEditor(table); editor.grabHorizontal = true; editor.grabVertical = true; // 将进度条绑定到第二列中 editor.setEditor(bar, item, 1); } //线程方法体,与前面单个的进度条的程序类似 public void run() { for (int i = min; i < max; i++) { if (isDone()) { break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } Display.getDefault().asyncExec(new Runnable(){ // table.getDisplay().asyncExec(new Runnable() { public void run() { if (bar.isDisposed()) return; bar.setSelection(bar.getSelection() + 1); } }); //如果停止,则结束该线程 } } public boolean isDone() { return done; } public static void setDone(boolean done) { Task.done = done; }}

解决方案

1,对于长时间的任务,不应该在图像线程中完成,如这里的增加1000项表项。应该另起一个线程,然后让图形线程来调度。public class MutiTaskGUI {private Shell shell = null; private Table table = null; private addItem t;public MutiTaskGUI( ){ init(); } //初始化窗口方法 public void init() {shell = new Shell(); shell.setSize(282, 240); shell.setLayout(new GridLayout());Button bt = new Button ( shell , SWT.NONE); bt.setText("开始一个任务"); //停止线程 Button stop = new Button(shell, SWT.NONE); stop.setText("stop"); table = new Table(shell, SWT.BORDER); table.setLayoutData( new GridData(SWT.FILL,SWT.FILL,true,true)); table.setHeaderVisible(true); table.setLinesVisible(true); String[] header = new String[]{"任务","进度","操作"}; // 创建表头 for (int i = 0; i < 3; i++) {TableColumn col = new TableColumn(table, SWT.NONE); col.setText( header[i] );}//设置表头宽度 table.getColumn(0).setWidth(80);table.getColumn(1).setWidth(150);table.getColumn(2).setWidth(80); //shell.pack();//注册创建任务按钮事件 bt.addSelectionListener( new SelectionAdapter(){ //当单击创建一个任务按钮时 public void widgetSelected(SelectionEvent e) {t = new addItem(table);t.start();/*//首先创建一个Task对象 for(int i = 0 ; i < 1000; i++) {Task task = new Task();//然后在表格中添加一行 task.createTableItem(table); //最后启动该任务,该任务为一个线程 task.start();}*/}}); stop.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent arg0) { t.setDone(true); }}); } public Shell getShell() {return shell;} public static void main(String[] args) {Display display = Display.getDefault(); MutiTaskGUI mutiTask= new MutiTaskGUI(); mutiTask.getShell().open();while (!mutiTask.getShell().isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); }}} } class addItem extends Thread {private Table table;public boolean done = false; public addItem(Table table) {this.table = table;}public void run() {//首先创建一个Task对象 for(int i = 0 ; i < 1000; i++) {//然后在表格中添加一行 try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();} if(isDone()) break;Display.getDefault().asyncExec(new Runnable() {public void run() {Task task = new Task();task.createTableItem(table); task.start();}});//最后启动该任务,该任务为一个线程 }}public boolean isDone() {return done;}public void setDone(boolean done) { this.done = done; }}class Task extends Thread {//是否停止的标志 public static boolean done = false; //声明进度条对象 private ProgressBar bar = null; private int min = 0; private int max = 100; int i = 0; //创建表格中的一行 public void createTableItem(Table table) {//done = false; TableItem item = new TableItem(table, SWT.NONE); item.setText(this.getName()); // 创建一个进度条 bar = new ProgressBar(table, SWT.NONE); bar.setMinimum(min); bar.setMaximum(max); // 创建一个可编辑的表格对象 TableEditor editor = new TableEditor(table); editor.grabHorizontal = true; editor.grabVertical = true; // 将进度条绑定到第二列中 editor.setEditor(bar, item, 1);}//线程方法体,与前面单个的进度条的程序类似 public void run() {for (int i = min; i < max; i++) {if (isDone()) {break;} try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();} Display.getDefault().asyncExec(new Runnable(){ // table.getDisplay().asyncExec(new Runnable() { public void run() { if (bar.isDisposed())return; bar.setSelection(bar.getSelection() + 1); }}); //如果停止,则结束该线程 } } public boolean isDone() {return done;}public static void setDone(boolean done) { Task.done = done; }}改了一下你的例子,你看看,改了一些你的格式,不要介意啊。希望 对你有帮助。

时间: 2024-09-20 21:19:27

swt 界面假死 使用asyncExec(runnable),没出现多线程的效果的相关文章

vc++ 关于windows窗体应用程序,线程与界面,线程不停,界面假死

问题描述 vc++ 关于windows窗体应用程序,线程与界面,线程不停,界面假死 clr程序,窗体应用程序,点击一个按钮,然后开启一个线程和服务器通信,通信一直进行,也就是线程不退出,界面就没反应了 请问怎么解决? 解决方案 你的线程必须是都堵塞的,否则会把CPU占满,如果不是,必须sleep: 解决方案二: 线程需要不一直占有CPU 需要适时的释放CPU 然后给界面线程做一些界面更新

阻塞-vb.net多线程造成窗体界面“假死”解决办法?

问题描述 vb.net多线程造成窗体界面"假死"解决办法? 我在一个窗体按钮单击事件里开了一个新线程用于连接一硬件设备,结果线程一start窗体就卡死了,造成窗体线程阻塞,我想知道时间片是如何分配的,默认优先级相同,为什新线程会独占时间片? 解决方案 我在编写MFC窗体程序时也测验过线程独占的情形,我猜想最可能的原因是:线程的开辟与管辖范围与主线程相干.

假死 重启浏览器-页面没有加载完,点击其他链接,就会死掉,必须重启浏览器才能再次访问

问题描述 页面没有加载完,点击其他链接,就会死掉,必须重启浏览器才能再次访问 最近在做一个内部管理系统,当一个页面没有加载完,点击其他链接,好像整个站点死掉了一样,必须重启浏览器才能再次访问,或者换个浏览器也能访问(例如当前用IE不能访问,再用360也是可以访问的).备注:假死的时候静态页面可以访问,动态页面访问不了,也不是数据库问题.不知道有没有大神遇到同样的问题,是怎么解决的?望指教! 解决方案 服务器加上断点和日志调试,看输出什么,在哪里挂起的.

winform修改DataGridView Cell界面假死问题

问题描述 DataGridView中更新用户所选的某列单元格的信息,如果选择的记录稍多一些修改的时候界面可能会假死,网上找些资料说可以用BeginInvoke和Thread解决.刚测试了下,如果用newThread直接操作DataGridView可以得到想要的结果即界面不会假死.如果用newThread再用BeginInvoke,界面还是会卡死.代码如下,请各位前辈多多指点.privatevoidbtn_Click(objectsender,EventArgse){//界面依旧会卡Threadt

winform 界面 假死 button 按钮 点击不了。。

问题描述 一共一千万个数字需要处理,每个事件各处理一百万个数字.....怎么完善 解决方案 解决方案二:页面加载我直接执行也卡死了..为什么.呢publicForm1(){InitializeComponent();for(inti=0;i<10;i++){//Buttonbtn=newButton();//btn.Location=newPoint(50,12+i*41);//btn.Name="b"+i;//btn.Text="生成"+i;//btn.Ta

分享一段“在.net的多线程中更新任意为Control类型的控件”解决窗体假死问题,调用极其简洁和方便~~~

问题描述 众所周知,在.net的多线程中更新界面时很容易假死,如果界面上有100个控件,那代码量又是相当的复杂,现提供一段简单的代码,可以用于线程代码的任意位置,而界面又不会假死.总之是一行代码,解决了一个复杂而又麻烦的大问题,让你完全不用考虑多线程下对控件的处理,直接调用就好了.1.适用范围:任意Control类型的控件.2.调用this.Label1.InvokeEx(e=>e.Text=DateTime.Now); 3.代码publicstaticvoidInvokeEx<T>(t

wxpython中利用线程防止假死的实现方法_python

前段时间我编写了一个工业控制的软件,在使用中一直存在一个问题,就是当软件检索设备时,因为这个功能执行的时间比较长,导致GUI界面假死,让用户分辨不清楚软件到底仍在执行,还是真的挂掉了.(虽然我设计了同步log显示,但是这个也同样假死了) 程序截图如下: 代码解析如下: # -*- coding: utf-8 -*- import time import wx from threading import Thread from wx.lib.pubsub import Publisher time

如何防止你的UI出现了假死吗?

如果应用程序在UI线程上执行非UI线程的耗时处理时,会使应用程序界面的运行显得缓慢而迟钝,有时会出现应用程序"UI界面假死"的现象,这也会引起用户的不满. .NET的多线程技术将耗时操作从UI线程中分离到另外一个工作线程中,可以有效的提高应用程序的响应能力,而采用异步委托调用方法实现多线程的管理可以使得程序结构清晰,编程简单.   我们要明确,为什么要进行异步回调?众所周知,普通方法运行,是单线程的,如果中途有大型操作(如:读取大文件,大批量操作数据库,网络传输等),都会导致方法阻塞,

拯救Win XP系统假死3招“妙计”

使用Windows XP时间比较长后,有时运行会很不流畅,甚至会不响应鼠标键盘对操作.很多时候是系统的假死.和真正的死机不同,假死完全可以被"救活".假死的根源在于 explorer.exe(整个图形界面的驱动).既然会假死,那就一定有解决方法,下面就为朋友们介绍一些拯救系统假死的方法. 第一招:当使用资源管理器打开新文件夹或用浏览器打开新页面不响应时,用"Win+D"或单击快速启动栏的显示桌面按钮,再在桌面上按F5或右键刷新即可.一般刷新3-5次后再把资源管理器或