Project

General

Profile

Wt::WTimer timeout callback in different thread and lost link - how to force it in one thread?

Added by jupiter hce about 3 years ago

Hi,

I created following code for a timer callback:

auto container = std::make_unique();
auto page = std::make_uniqueWt::WText(tr("home.installBootloader.status"));
auto *t = this->addWidget(std::make_uniqueWt::WTemplate(tr("home.bootloader.status")));
this->mTextArea = std::make_uniqueWt::WTextArea("Status:");
this->mTimer = std::make_uniqueWt::WTimer();
this->mTimer->setInterval(std::chrono::milliseconds{this->mIntervalMillisecond});
this->mTimer->timeout().connect(this, &BootloaderImplement::Inspection);
this->mTimer->start();

The timer is called every 5 seconds, in the callback BootloaderImplement::Inspection(), it called this->mTextArea but that pointer was no longer a valid pointer, thus the his->mTextArea->setText could not be called. Does the Wt::WTimer creat a new thread to call BootloaderImplement::Inspection? If so, how can I force the Wt::WTimer to use a single thread? I have already used --threads 1 when launch the binary.

void BootloaderImplement::Inspection(void) {
if (this->mTextArea) {
this->mTextArea->setText("do some thing");
}
}

Thank you.

Kind regards,

  • jupiter

Replies (4)

RE: Wt::WTimer timeout callback in different thread and lost link - how to force it in one thread? - Added by Korneel Dumon about 3 years ago

Hi,

your mTextArea is never added to the widget tree. And if you would do it later, you would have to move it out of mTextArea making the pointer invalid.
If you want to keep the textarea around for later changes, you should use a raw pointer. Something like:

WTextArea *mTextArea = container->addWidget(std::make_unique<WTextArea>("Status"));

WTimer events are handled in the event-loop, so threading is not an issue.

RE: Wt::WTimer timeout callback in different thread and lost link - how to force it in one thread? - Added by jupiter hce about 3 years ago

Thanks Korneel.

TextArea *mTextArea = container->addWidget(std::make_unique("Status")) caused an compiler error:

error: no match for ‘operator=’ (operand types are ‘std::unique_ptrWt::WTextArea’ and ‘Wt::WTextArea*’)

I made a little bit clean up:

class BootloaderImplement : public Wt::WContainerWidget {
};

void BootloaderImplement::Run(void) {
auto *t = this->addWidget(std::make_uniqueWt::WTemplate(tr("home.bootloader.status")));
// this->mTextArea = this->addWidget(std::make_uniqueWt::WTextArea("Status:")); // compile error: no match for ‘operator=’
this->mTextArea = std::make_uniqueWt::WTextArea("Status:");
t->bindWidget("install-bootloader-status", std::move(this->mTextArea));
this->mTimer = std::make_uniqueWt::WTimer();
this->mTimer->setInterval(std::chrono::milliseconds{this->mIntervalMillisecond});
this->mTimer->timeout().connect(this, &BootloaderImplement::Inspection);
this->mTimer->start();
}

Are there anything wrong or missing in above code? The this->mTextArea is still an invalid pointer in BootloaderImplement::Inspection.

Thank you.

Kind regards,

  • jupiter

RE: Wt::WTimer timeout callback in different thread and lost link - how to force it in one thread? - Added by Korneel Dumon about 3 years ago

The same kind of function exists for templates

this->mTextArea = t->bindWidget("install-bootloader-status", std::make_unique<Wt::WTextArea>("Status:"));

You don't need to store smart pointers to widgets yourself, Wt manages it all in a widget tree. Use raw pointers as your member variables.

RE: Wt::WTimer timeout callback in different thread and lost link - how to force it in one thread? - Added by jupiter hce about 3 years ago

Thanks Korneel, use raw pointer does the trick.

Thank you so much.

    (1-4/4)