本文最后更新于 2025年6月10日 晚上
                  
                
              
            
            
              
                
                报错原因
我最近在做一个 Dns 测速软件,目前为止它长这样

而问题就出现在这里,这个进度条

我想实现的效果是每测试完一个 IP 就自动更新 Progress,代码是这样写到(最后几行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
   | void DnsSpeedTester::RunPing(int num) {     int rowCount = model->rowCount();     QMutex mutex;  
      QList<QFuture<void>> futures;  
      for (int row = 0; row < rowCount; ++row) {         QFuture<void> future = QtConcurrent::run([=, &mutex]() {             CPing P;             QModelIndex index = model->index(row, 0);             QVariant data = index.data(Qt::DisplayRole);             QString tmp_IP = data.value<QString>();             QByteArray temp = tmp_IP.toLatin1();             char* IP = temp.data();
                           {                 QMutexLocker locker(&mutex);                 model->setData(model->index(row, 2), "测量中");             }
              int delay = P.pings(IP, num);
 
                           {                 QMutexLocker locker(&mutex);                 if(delay>999999){                 model->setData(model->index(row, 2), "请求超时");                                  QColor color = QColor(Qt::red);                 model->setData(model->index(row,2), color, Qt::ForegroundRole);                 }                 else{                     model->setData(model->index(row, 2), delay);                                          QColor color;                     if (delay < 50) {                         color = QColor(98, 151, 52);                     } else if (delay < 100) {                         color = QColor(255, 150, 63);                     } else {                         color = QColor(255, 73, 73);                     }                     model->setData(model->index(row,2), color, Qt::ForegroundRole);                 }
              }
              qDebug() << "行:" << row << " IP:" << IP << " 延迟:" << delay;         });
          futures.append(future);           PingedIP++;         Progress=PingedIP/AllIP;         ui->progressBar->setValue(Progress*100);
      }
 
  | 
 
可以看见我这里使用QtConcurrent::run来防止线程阻塞,然后又尝试修改progressBar的值,然后程序就直接崩溃了,而且 Debug 全是汇编和内存地址,啥也看不懂,后来才知道:
在 QtConcurrent::run 中使用了 lambda 表达式,该表达式默认建立在被捕获变量的副本上运行。在你的代码中,你在 lambda 表达式中访问了 ui 的成员,这是不被允许的,因为在另一个线程中操作 GUI 对象可能会导致线程冲突或其他异常。
解决方案
那么这种问题要怎么解决呢?
答案就是使用信号和槽机制,使修改操作在原 UI 线程中操作
一下是我的修改
首先在头文件中定义一个信号和槽
1 2 3 4
   | signals:     void updateProgressBarSignal(int value); public slots:     void onUpdateProgressBar(int value);
 
  | 
 
由于我这里是要修改 progressbar 的值,所以要一个 int 类型的值,然后再源文件中实现该槽函数
1 2 3 4
   | void DnsSpeedTester::onUpdateProgressBar(int value) {     ui->progressBar->setValue(value); }
 
  | 
 
最后将原来是直接修改的部分,改为发送一个信号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
   | QFuture<void> future = QtConcurrent::run([=, &mutex]() {             CPing P;             QModelIndex index = model->index(row, 0);             QVariant data = index.data(Qt::DisplayRole);             QString tmp_IP = data.value<QString>();             QByteArray temp = tmp_IP.toLatin1();             char* IP = temp.data();
                           {                 QMutexLocker locker(&mutex);                 model->setData(model->index(row, 2), "测量中");             }
              int delay = P.pings(IP, num);             PingedIP++;             Progress=PingedIP/AllIP;             emit updateProgressBarSignal(Progress*100);             qDebug()<<Progress*100;
                           {                 QMutexLocker locker(&mutex);                 if(delay>999999){                 model->setData(model->index(row, 2), "请求超时");                                  QColor color = QColor(Qt::red);                 model->setData(model->index(row,2), color, Qt::ForegroundRole);                 }                 else{                     model->setData(model->index(row, 2), delay);                                          QColor color;                     if (delay < 50) {                         color = QColor(98, 151, 52);                     } else if (delay < 100) {                         color = QColor(255, 150, 63);                     } else {                         color = QColor(255, 73, 73);                     }                     model->setData(model->index(row,2), color, Qt::ForegroundRole);                 }
              }
 
  | 
 
这样再运行就不会崩溃了