我正在为3D打印机开发Qt界面。当我点击打印按钮(打印机开始打印)时,界面崩溃。我正在使用以下代码:
*future= QtConcurrent::run(Imprimir,filename.toUtf8().data());
我可以用什么来解决它??我可以使用哪些类型的线程????
我需要在打印机打印时使用界面(可能需要几分钟)。
谢谢你的提前。
编辑:
Imprimir
功能:
int Imprimir(char *fich)
{
char *aux = new char;
FILE *f;
f=fopen(fich, "r");
while(!feof(f)){
fgets(aux, 200, f);
Enviar(aux);
while(!seguir_imprimiendo);
}
Sleep(7000);
return 0;
}
不使用QFile
使生活变得比必要的更难。当你使用QFile
时,你不必处理愚蠢的事情,比如传递C字符串文件名。您可能会做错,因为谁能保证平台希望它们以UTF-8
编码。Qt的全部意义在于它可以帮助您避免此类问题。它们得到照顾,代码在多个平台上进行测试,以确保每种情况下的行为都是正确的。
如果不使用 QByteArray
和 QFile
,您很可能会犯一些愚蠢的错误,例如分配单个字符缓冲区然后假装它有 200 个字符长的 C 经典错误。
我认为没有理由用这种方法睡觉。等待继续标志seguir_imprimiendo
更改也是没有意义的,因为Enviar
在同一线程中运行。它应该阻止,直到发送数据。
我假设你也已经通过QtConcurrent::run
运行了Enviar
代码。这是不必要的,并导致死锁。想一想,如果空闲线程在运行时永远不可用Imprimir
会发生什么。对于运行Imprimir
池限制为仅一个线程是有效的。你不能简单地假装它不会发生。
bool Imprimir(const QString & fileName)
{
QFile src(fileName);
if (! src.open(QIODevice::ReadOnly)) return false;
QByteArray chunk;
do {
chunk.resize(4096);
qint64 read = src.read(chunk.data(), chunk.size());
if (read < 0) return false;
if (read == 0) break; //we're done
chunk.resize(read);
if (!Enviar(chunk)) return false;
} while (! src.atEnd());
return true;
}
bool Enviar(const QByteArray & data)
{
...
return true; // if successful
}
假设Imprimir
没有问题,问题可能出在filename.toUtf8().data()
上。从此函数获取的数据指针仅在filename
范围内有效。当filename
超出范围时,数据可能会被删除,并且访问数据的任何代码都将崩溃。
为了安全起见,应更改Imprimir
函数以接受QString
参数,而不是char*
。
如果您无法更改Imprimir
函数(例如,因为它在另一个库中),则必须将其包装在您自己的接受 QString 的函数中。如果您使用的是 C++11,则可以使用 lambda 表达式来完成这项工作:
QtConcurrent::run([](QString filename) {
Imprimir(filename.toUtf8().data());
}, filename);
如果没有,则必须编写一个单独的ImprimirWrapper(QString filename)
函数并使用QtConcurrent::run
调用它。