vb.net多线程,循环导致窗口界面假死的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vb.net多线程,循环导致窗口界面假死的问题相关的知识,希望对你有一定的参考价值。

程序中有一个ProgressBar
定义有变量:
Dim i as integer
Delegate Sub deSomeSub()
Dim T As System.Threading.Thread
过程:
Sub SomeSub()
For i = 0 To ListView1.Items.Count - 1
Dim b As Bitmap = Bitmap.FromFile("文件路径")
Dim a As Bitmap = ZommPictureto480(b)
a.Save("存储路径", System.Drawing.Imaging.ImageFormat.Jpeg)
b.Dispose()
a.Dispose()
ProgressBar.PerformStep()
Next
End Sub

Sub BeginDoSub()
Dim s As New deSomeSub(AddressOf SomeSub)
Me.Invoke(s)
End Sub

Button点击事件:
Sub Click
ProgressBar.Maximum = ListView1.Items.Count
T = New Threading.Thread(New Threading.ThreadStart(AddressOf SomeSub))
T.Start()
End Sub

'---------------------------------------------------------------
上面程序在执行的时候一旦ListView中的项目很多,进行多次循环的时候(大概在100次左右)就会使窗口界面假死,无法进行操作,但是程序仍然是在运行中。不知道有哪位知道这是什么问题吗?
Button点击事件中应该是:
T = New Threading.Thread(New Threading.ThreadStart(AddressOf BeginDoSub))

本来就是要运行速度最快,还设置停顿?

同学。。你这里的写法其实根本没有用到多线程
原因很简单
你是定义了一个T的新线程,但是很可惜你在BeginDoSub这个独立的线程中又定义了一个deSomeSub的委托,并且直接用Me.Invoke把实际的执行任务提交给界面主线程运行了
所以你的图片的处理函数实际上是在主线程中运行的,新线程等于没用

正确的作法是,T定义为SomeSub这个函数为入口的线程,并启动它
在界面进度条更改的时候再使用Invoke来调用委托来进行界面更改。

自己再好好看看吧,时间问题我要走了。
参考技术A 设置下 线程 的停顿时间

线程 很多快速的运行是否会导致窗口界面假死呢?

QT多线程之---moveToThread用法

  在gui编程里,一个子函数的运行时间可能过长,界面就处于假死状态,原因是窗口是一个线程,子函数也在这个线程里,一些事件也要在这个线程里处理。

如果子函数运行时间过长,系统没有办法调用事件监听循环,gui就处于假死。一般有两种办法:

      子函数事件不是很长,可以在子函数中间插入一些 QCoreApplication::processEvents 

       另一种方法就是把耗时的工作放到另一个线程里,通过信号槽来传递。这里介绍Qobject的moveToThread方法。

       下面使用老板和员工的例子来讲,有两个BT老板,闲的蛋疼,安了个闹钟,每个一段时间查员工的岗。

代码如下:

  

#include <QCoreApplication>
#include <QThread>
#include <QTimer>
#include <QObject>
#include <QDebug>
#include "worker.h"
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qDebug()<<"main thread is :"<<QThread::currentThreadId()<<endl;    //打印主线程的线程号
   
QTimer *boss1 = new QTimer(); boss1->setInterval(5000); QThread *t1=new QThread(); //来一个新的线程 t1->start(); //启动线程 Worker w1("Bob"); //创建一个对象 w1.moveToThread(t1); //把这个对象移到线程t1里 QObject::connect(boss1, SIGNAL(timeout()), &w1, SLOT(run())); //通过信号槽机制将boss1和worker1连接起来,每个一段时间查一次看看员工工作没 QTimer *boss2 =new QTimer();
boss2->setInterval(3000); QThread *t2=new QThread(); //来一个新的线程 t2->start(); //启动线程 Worker w2("Stuart"); //创建一个对象 w2.moveToThread(t2); //把这个对象移到线程t2里 QObject::connect(boss2, SIGNAL(timeout()), &w2, SLOT(run())); boss1->start(); boss2->start(); return a.exec(); }

 worker类

  注意的是worker类一定要继承Qobject

#ifndef WORKER_H
#define WORKER_H

#include <QObject>
#include <iostream>
class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QString name, QObject *parent = nullptr);
    long runnum=0;
    QString name;

signals:

public slots:
    void run(void);
};

#endif // WORKER_H

 

#include "worker.h"
#include <QDebug>
#include <QThread>
Worker::Worker(QString name ,QObject *parent) : name(name),QObject(parent)
{
    qDebug()<<"Hi, I‘m worker:"<<name<<" at thread number:"<<QThread::currentThreadId()<<endl;
}

void Worker::run()
{
    runnum++;
    qDebug()<<"I‘m "<<name<<" don‘t spy me so frequently boss! I‘m busy in my work..........";
    qDebug()<<"you have spy me "<<runnum<<" times!"<< "I‘m working at thread num :"<<QThread::currentThreadId()<<endl;
    long s=1000;
    for (long i=0; i<s;i++){


    }

}

 运行后的结果:

main thread is : 0x6be0

Hi, I‘m worker: "Bob"  at thread number: 0x6be0

Hi, I‘m worker: "Stuart"  at thread number: 0x6be0

I‘m  "Stuart"  don‘t spy me so frequently boss! I‘m busy in my work..........
you have spy me  1  times! I‘m working at thread num : 0x36c0

I‘m  "Bob"  don‘t spy me so frequently boss! I‘m busy in my work..........
you have spy me  1  times! I‘m working at thread num : 0x5ff0

I‘m  "Stuart"  don‘t spy me so frequently boss! I‘m busy in my work..........
you have spy me  2  times! I‘m working at thread num : 0x36c0

I‘m  "Stuart"  don‘t spy me so frequently boss! I‘m busy in my work..........
you have spy me  3  times! I‘m working at thread num : 0x36c0

I‘m  "Bob"  don‘t spy me so frequently boss! I‘m busy in my work..........
I‘m  "Stuart"  don‘t spy me so frequently boss! I‘m busy in my work..........
you have spy me  2  times! I‘m working at thread num : 0x5ff0

you have spy me  4  times! I‘m working at thread num : 0x36c0

I‘m  "Bob"  don‘t spy me so frequently boss! I‘m busy in my work..........
I‘m  "Stuart"  don‘t spy me so frequently boss! I‘m busy in my work..........

 

不知道你们又遇到BT的老板吗。

 

以上是关于vb.net多线程,循环导致窗口界面假死的问题的主要内容,如果未能解决你的问题,请参考以下文章

VB.NET程序界面假死如何解决

vb.net 多线程调用另一窗口,假死现象,如何解决

vb.net 多线程 窗体 假死

C#多线程实现循环。界面会假死怎么办?

VB.net可以多线程控制同一个窗体及其控件吗

C#程序窗口假死