Теперь мой код выглядит так:
Код: Выделить всё
//main.cpp
#include
#include "backend.h"
class MainFrame : public wxFrame {
public:
MainFrame(BackendService& svc)
: wxFrame(nullptr, wxID_ANY, "Backend Example"), svc_(svc) {
wxBoxSizer* s = new wxBoxSizer(wxVERTICAL);
btnStart_ = new wxButton(this, wxID_ANY, "Start");
prg_ = new wxGauge(this, wxID_ANY, 100);
lbl_ = new wxStaticText(this, wxID_ANY, "Idle");
s->Add(btnStart_, 0, wxALL|wxEXPAND, 5);
s->Add(prg_, 0, wxALL|wxEXPAND, 5);
s->Add(lbl_, 0, wxALL, 5);
SetSizerAndFit(s);
btnStart_->Bind(wxEVT_BUTTON, &MainFrame::OnStart, this);
// subscribe to backend updates
svc_.setProgressCallback([this](const Progress& p){
// marshal to main thread
wxApp::GetInstance()->CallAfter([this, p]() {
prg_->SetValue(p.percent);
lbl_->SetLabel(p.status + " " + std::to_string(p.percent) + "%");
});
});
}
~MainFrame() {
svc_.stop();
}
private:
void OnStart(wxCommandEvent&) {
svc_.startLongTask();
}
BackendService& svc_;
wxButton* btnStart_;
wxGauge* prg_;
wxStaticText* lbl_;
};
class MyApp : public wxApp {
public:
bool OnInit() override {
frame_ = new MainFrame(svc_);
frame_->Show();
return true;
}
int OnExit() override { svc_.stop(); return 0; }
private:
BackendService svc_;
MainFrame* frame_{nullptr};
};
wxIMPLEMENT_APP(MyApp);
Код: Выделить всё
//backend.h
#pragma once
#include
#include
#include
#include
struct Progress {
int percent;
std::string status;
};
class BackendService {
public:
using ProgressCb = std::function;
BackendService();
~BackendService();
void startLongTask();
void stop();
void setProgressCallback(ProgressCb cb);
private:
void workerLoop();
ProgressCb progressCb_;
std::thread workerThread_;
std::atomic running_;
};
Код: Выделить всё
//backend.cpp
#include "backend.h"
#include
BackendService::BackendService() : running_(false) {}
BackendService::~BackendService() { stop(); }
void BackendService::setProgressCallback(ProgressCb cb) {
progressCb_ = std::move(cb);
}
void BackendService::startLongTask() {
if (running_) return;
running_ = true;
workerThread_ = std::thread(&BackendService::workerLoop, this);
}
void BackendService::stop() {
if (!running_) return;
running_ = false;
if (workerThread_.joinable()) workerThread_.join();
}
void BackendService::workerLoop() {
for (int i = 0; i
Подробнее здесь: [url]https://stackoverflow.com/questions/79846494/wxwidgets-crash-due-to-not-finished-joined-thread-when-using-callbacks-to-sepa[/url]
Мобильная версия