当Windows屏幕锁定时,新的QFile(“some.txt”)因“设备未打开”而失败

时间:2017-12-05 12:08:03

标签: windows qt qt5 qfile qt5.9

考虑这个非常简单的例子:

//abs(Cx*(y1-y0)-Cy*(x1-x0)+x1*y0-y1*x0)/sqrt((y1-y0)*(y1-y0)+(x1-x0)*(x1-x0))<R
//pull out some constants and cache these as they are initialized
//int y10 = y1-y0, //add to the line struct
//  x10 = x1 -x0,
//  delta = x1*y0-y1*x0,
//  sides = (y10)*(y10)+(x10)*(x10);
//  R2 = R*R; //add to the circle struct
//now the equation factors down to
//abs(Cx*(y10)-Cy*(x10)+delta)/sqrt(sides)< R //replace constants
//abs(Cx*(y10)-Cy*(x10)+delta) < sqrt(sides) * R //remove division
//pow(Cx*(y10)-Cy*(x10)+delta , 2.0) < sides * R * R //remove sqrt()
//int tmp = Cx*(y10)-Cy*(x10)+delta //factor out pow data
//tmp * tmp < sides * R2 //remove pow() and use cache R squared
//now it is just a few cheap instructions

直到最近Windows屏幕被锁定时,它仍然正常工作,但我不确定它是否开始像这样,因为我开始使用Qt 5.9或者如果它是一个Windows更新,阻止文件访问Windows屏幕被锁定。

因此,请告知解决方法或解决方案。 谢谢。

编辑: 事实证明,QFile或文件访问不是问题,问题在于调用它的位置和方式。所以我接受了@Kuba的回答,因为它提供了信息并且方向正确。

1 个答案:

答案 0 :(得分:0)

您的代码泄漏了内存和资源:QFile实例永远不会被销毁,因为您永远不会让事件循环在当前线程中运行,并且它是会破坏它们的事件循环。

没有理由在堆上创建文件对象,也没有任何理由明确关闭文件:QFile是一个实现RAII的正确C ++类。在任何状态下销毁它都是安全的,没有资源泄漏。只需销毁文件即可关闭其底层句柄。

结合上述建议,代码应为:

for (;;){
   QFile file("some.txt");
   if (file.exists()){
      file.open(QFile::ReadOnly);
      auto contents = file->readAll();
      qDebug() << "read, n=" << contents.size();
   }
   QThread::sleep(2);
}

但理想情况下,您应该从事件循环中运行代码而不是阻塞线程。线程是昂贵的资源,并且拥有一个在大多数时间都不做任何事情的线程是相当浪费的。

auto timer = new QTimer;
timer->start(2000);
auto reader = []{
  QFile file("some.txt");
  if (file.exists()){
    file.open(QFile::ReadOnly);
    auto contents = file->readAll();
    qDebug() << "read, n=" << contents.size();
  }
});
connect(timer, &QTimer::timeout, reader);

要结束阅读,请停止或销毁计时器。

线程应该旋转一个事件循环 - QThread::run的默认实现将为您完成。因此,上面的代码可以包装在QObject中并移动到专用线程,该线程也应该用于其他事情。

或者,您可以使用线程池并在工作线程中执行读取,但在GUI线程中运行计时器。只需将上面的connect语句更改为:

connect(timer, &QTimer::timeout, [reader]{ QtConcurrent::run(reader); });