为了避免阻塞UI线程,我在Qt中将一些I/O代码移到了QRunnable中。这将以一些排队的插槽进行回调以指示其进度。

但是我最近看到了一些问题,当QRunnable的所有者被销毁时,它无法删除可运行对象,直到其完成(否则崩溃,因为工作线程仍在使用它)。为了解决这个问题,我想在可运行对象中添加一个“WaitForFinished”,它将在dtor中调用它,因此我可以简单地删除QRunnable并知道它会阻塞,直到它在dtor退出之前完成。

我认为这应该很容易,因为我需要做的就是在QMutex实现中使用QRunnable::run,然后在WaitForFinished中获取该互斥量。但是,这有一个竞赛条件,我不确定该如何解决。

考虑以下:

  • QRunnable排队等待执行。
  • QRunnable开始执行,但尚未将QRunnable::run称为
  • 主线程删除在dtor中调用QRunnableWaitForFinished,并在QMutex之前获取QRunnable::run-因此我们假设其未运行或未完成运行并破坏了QRunnable,但它甚至还没有开始!
  • 最佳答案

    首先,没有一个适合所有解决方案的尺寸。首选方法将取决于任务详细信息。尽管我问了一些问题,但仍然存在很多歧义。但是,我将描述我能想到的最简单的方法。

  • 启用Runnables自动删除
  • 每次在所有者对象中启动新作业时,创建一些startedJobsCounter并增加它。
  • 创建作业结束时将其释放的信号灯finishedJobsSem
  • 所有Runnable的waitForFinished看起来像

    finishJobsSem.aquire(startedJobsCounter);
  • 您可以在可运行的析构函数中释放finishedJobsSem
  • startedJobsCounter读写之间没有竞争,因为它们都是在所有者的对象线程中执行的。

    由于所有作业都将在销毁所有者对象之前完成,因此finishedJobsSem不能无效地使用可运行格式。

    10-04 20:20