报错原因
我最近在做一个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); }
}
|
这样再运行就不会崩溃了
更新预告
我的DNS测速软件也快要写完了,给大家看一下演示效果,开发进度70%
开发进度