WxWidgets — сбой из-за незавершенного/неприсоединенного потока при использовании обратных вызовов для разделения внутренC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 WxWidgets — сбой из-за незавершенного/неприсоединенного потока при использовании обратных вызовов для разделения внутрен

Сообщение Anonymous »

Я пытаюсь устранить проблему, с которой столкнулся при попытке отделить серверную часть от графического пользовательского интерфейса. Первоначально я успешно реализовал многопоточность в одном основном классе wxFrame на основе этого руководства: wx_stdthread_tutorial. Я работаю на Linux Mint, а IDE — Clion.
Теперь мой код выглядит так:

Код: Выделить всё

//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]
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»