The workers run in separate threads meaning if any significant change is made (e.g. parameters changing, or even closing the program), these workers may still be mid-render. This is particularly problematic when closing since the nodes a worker is rendering may be deleted mid-render. Render backends now have a function that pauses the main thread (but starts a second event loop so the UI isn't frozen) until the worker threads are all finished. This way, massive changes can be made safely without race conditions.
57 lines
974 B
C++
57 lines
974 B
C++
#include "rendercancel.h"
|
|
|
|
RenderCancelDialog::RenderCancelDialog(QWidget *parent) :
|
|
LoadSaveDialog(tr("Waiting for workers to finish..."), tr("Renderer"), parent),
|
|
busy_workers_(0),
|
|
total_workers_(0)
|
|
{
|
|
}
|
|
|
|
void RenderCancelDialog::RunIfWorkersAreBusy()
|
|
{
|
|
if (busy_workers_ > 0) {
|
|
waiting_workers_ = busy_workers_;
|
|
|
|
exec();
|
|
}
|
|
}
|
|
|
|
void RenderCancelDialog::SetWorkerCount(int count)
|
|
{
|
|
total_workers_ = count;
|
|
|
|
UpdateProgress();
|
|
}
|
|
|
|
void RenderCancelDialog::WorkerStarted()
|
|
{
|
|
busy_workers_++;
|
|
|
|
UpdateProgress();
|
|
}
|
|
|
|
void RenderCancelDialog::WorkerDone()
|
|
{
|
|
busy_workers_--;
|
|
|
|
UpdateProgress();
|
|
}
|
|
|
|
void RenderCancelDialog::showEvent(QShowEvent *event)
|
|
{
|
|
UpdateProgress();
|
|
}
|
|
|
|
void RenderCancelDialog::UpdateProgress()
|
|
{
|
|
if (!total_workers_ || !isVisible()) {
|
|
return;
|
|
}
|
|
|
|
SetProgress(qRound(100.0 * static_cast<double>(waiting_workers_ - busy_workers_) / static_cast<double>(waiting_workers_)));
|
|
|
|
if (busy_workers_ == 0) {
|
|
accept();
|
|
}
|
|
}
|