如何在 QT Web Assembly 中返回值之前等待异步 lambda 函数完成
How to wait for Async lamda function to finish before returning value in a QT Web Assembly
所以我用 Qt 为我的论文写了一个程序,现在我应该把它变成一个工作的 Web 程序集,这不是一个真正的问题,除了文件下载部分。我重写了我的文件下载方法:
QString costumfile::read(QString filename){
QString fileName = QFileDialog::getOpenFileName(nullptr, filename, "", "Text Files (*.txt )");
QFile file(filename);
qDebug()<<filename<<"filename";
if(!file.open(QFile::ReadOnly |
QFile::Text))
{
qDebug() << " Could not open the file for reading";
return "";
}
QTextStream in(&file);
QString myText = in.readAll();
//qDebug() << myText;
file.close();
return myText;
}
为此:
QString costumfile::read(QString filename)
{
QMessageBox msgBox;
QString textUser="Open" + filename;
msgBox.setText(textUser);
msgBox.exec();
QString text="hallo";
qDebug()<<filename;
auto fileContentReady = [&](const QString &fileName, const QString &fileContent) {
if (fileName.isEmpty()) {
msgBox.setText("Error");
msgBox.exec();
} else {
text=fileContent;
qDebug()<<text<<"texstis";
return fileContent;
}
return fileContent;
};
QFileDialog::getOpenFileContent(".txt", fileContentReady);
}
问题是 return 不等待 lambda 函数,因为它是异步的...
然后我尝试使用事件循环,它在 Destop 应用程序中运行良好,但在 webassembly 应用程序中不受支持。
那么有人知道如何等待 fileContentReady 函数吗?
据我所知,Qt for WebAssembly 目前不支持使用事件循环等待(至少 Qt 6.2 不支持)。参见 Qt 维基:
“不支持嵌套事件循环。应用程序不应调用 QDialog::exec() 或创建新的 QEventLoop 对象。”
https://wiki.qt.io/Qt_for_WebAssembly
所以您将不得不修改您的方法来处理异步调用。我的意思是,无论您想对文件做什么,都可以直接写入您拥有的 fileContentReady lambda。如果这是一个通用函数,您可以让调用者注册一个 done
回调,以便在文件准备好时执行。类似于:
QString costumfile::read(QString filename,
const std::function<void(const QString&)>& done)
{
...
auto fileContentReady = [=](const QString &fileName, const QString &fileContent) {
if (fileName.isEmpty()) {
// Report error
} else {
text=fileContent;
qDebug()<<text<<"texstis";
done(text);
}
};
QFileDialog::getOpenFileContent(".txt", fileContentReady);
}
// When calling costumfile::read
read(filename, [=] (const QString& text) {
// Do something with `text`
});
另外,关于QMessageBox的用法exec()
。这也可能导致问题,因为它在内部创建了一个嵌套的事件循环,Qt for WebAssembly 尚不支持该循环。而是使用 show()
方法。
auto msgBox = new QMessageBox();
msgBox->setText(textUser);
connect(msgBox, &QMessageBox::finished, &QMessageBox::deleteLater);
msgBox->show();
所以我用 Qt 为我的论文写了一个程序,现在我应该把它变成一个工作的 Web 程序集,这不是一个真正的问题,除了文件下载部分。我重写了我的文件下载方法:
QString costumfile::read(QString filename){
QString fileName = QFileDialog::getOpenFileName(nullptr, filename, "", "Text Files (*.txt )");
QFile file(filename);
qDebug()<<filename<<"filename";
if(!file.open(QFile::ReadOnly |
QFile::Text))
{
qDebug() << " Could not open the file for reading";
return "";
}
QTextStream in(&file);
QString myText = in.readAll();
//qDebug() << myText;
file.close();
return myText;
}
为此:
QString costumfile::read(QString filename)
{
QMessageBox msgBox;
QString textUser="Open" + filename;
msgBox.setText(textUser);
msgBox.exec();
QString text="hallo";
qDebug()<<filename;
auto fileContentReady = [&](const QString &fileName, const QString &fileContent) {
if (fileName.isEmpty()) {
msgBox.setText("Error");
msgBox.exec();
} else {
text=fileContent;
qDebug()<<text<<"texstis";
return fileContent;
}
return fileContent;
};
QFileDialog::getOpenFileContent(".txt", fileContentReady);
}
问题是 return 不等待 lambda 函数,因为它是异步的... 然后我尝试使用事件循环,它在 Destop 应用程序中运行良好,但在 webassembly 应用程序中不受支持。
那么有人知道如何等待 fileContentReady 函数吗?
据我所知,Qt for WebAssembly 目前不支持使用事件循环等待(至少 Qt 6.2 不支持)。参见 Qt 维基:
“不支持嵌套事件循环。应用程序不应调用 QDialog::exec() 或创建新的 QEventLoop 对象。” https://wiki.qt.io/Qt_for_WebAssembly
所以您将不得不修改您的方法来处理异步调用。我的意思是,无论您想对文件做什么,都可以直接写入您拥有的 fileContentReady lambda。如果这是一个通用函数,您可以让调用者注册一个 done
回调,以便在文件准备好时执行。类似于:
QString costumfile::read(QString filename,
const std::function<void(const QString&)>& done)
{
...
auto fileContentReady = [=](const QString &fileName, const QString &fileContent) {
if (fileName.isEmpty()) {
// Report error
} else {
text=fileContent;
qDebug()<<text<<"texstis";
done(text);
}
};
QFileDialog::getOpenFileContent(".txt", fileContentReady);
}
// When calling costumfile::read
read(filename, [=] (const QString& text) {
// Do something with `text`
});
另外,关于QMessageBox的用法exec()
。这也可能导致问题,因为它在内部创建了一个嵌套的事件循环,Qt for WebAssembly 尚不支持该循环。而是使用 show()
方法。
auto msgBox = new QMessageBox();
msgBox->setText(textUser);
connect(msgBox, &QMessageBox::finished, &QMessageBox::deleteLater);
msgBox->show();