如何在QtCreator中使用std::thread?MJPEG流代码集成异常求助
Let's break down your problem step by step—you've got a working C++11 MJPEG stream using std::thread, but it's failing silently in Qt Creator (compiles fine, browser can't see the stream), even after integrating robotvision's show_frame to pass frames to your streamer thread. Here's how to fix this, plus best practices for using std::thread in Qt:
First: Fix the MJPEG Stream Not Working in Qt
1. Fix Thread-Safe Frame Passing Between UI and Streamer Threads
The most likely culprit here is unsafe frame transfer from Qt's UI thread (where show_frame runs) to your Videostreamer thread. Qt's UI thread updates frames quickly, so if you're passing pointers/references instead of deep copies, the streamer thread will end up with invalid, overwritten data.
Do this instead:
- Deep-copy frames before passing them to the streamer:
void show_frame(const cv::Mat& frame) { // Clone the frame to avoid dangling references cv::Mat frame_copy = frame.clone(); your_videostreamer->push_frame(std::move(frame_copy)); } - Make your streamer's frame queue thread-safe with mutexes and condition variables to prevent race conditions:
class Videostreamer { private: std::queue<cv::Mat> frame_queue; std::mutex queue_mutex; std::condition_variable frame_ready_cv; std::atomic<bool> is_running = true; public: void push_frame(cv::Mat frame) { std::lock_guard<std::mutex> lock(queue_mutex); frame_queue.push(std::move(frame)); frame_ready_cv.notify_one(); } void run_stream() { while (is_running) { std::unique_lock<std::mutex> lock(queue_mutex); // Wait until a frame is available or we need to stop frame_ready_cv.wait(lock, [this](){ return !frame_queue.empty() || !is_running; }); if (!is_running) break; cv::Mat current_frame = std::move(frame_queue.front()); frame_queue.pop(); lock.unlock(); // Encode current_frame to MJPEG and send over network encode_and_send(current_frame); } } void stop() { is_running = false; frame_ready_cv.notify_one(); } };
2. Ensure Network IO Isn't Blocked by Qt's Event Loop
If your original stream uses raw sockets, double-check that:
- The socket is properly bound and listening in your
std::thread(Qt's network modules likeQTcpSocketwon't interfere unless you're using them, but port conflicts are possible). - You're not calling any Qt UI/network functions from the stream thread—stick to raw C++ socket operations here to avoid event loop conflicts.
- Add debug prints to verify:
- Is the stream thread receiving frames from
show_frame? - Is the socket accepting browser connections?
- Is MJPEG data actually being sent over the socket?
- Is the stream thread receiving frames from
3. Manage std::thread Lifecycle With Qt's Object Lifecycle
Qt objects have strict destruction rules—if your std::thread outlives the Qt object that owns it, you'll get crashes or silent failures.
In your Qt widget/class:
class MainWindow : public QMainWindow { private: Videostreamer streamer; std::thread stream_thread; public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { // Start the stream thread after initializing everything stream_thread = std::thread(&Videostreamer::run_stream, &streamer); } ~MainWindow() { // Stop the streamer and wait for the thread to finish streamer.stop(); if (stream_thread.joinable()) { stream_thread.join(); } } };
Correct std::thread Usage in Qt Creator
Here are non-negotiable rules to avoid headaches:
- Never manipulate Qt objects from non-UI threads: Most Qt classes (e.g.,
QWidget,QImage,QTcpSocket) are not thread-safe. Use Qt's signal-slot system withQt::QueuedConnectionto pass data between threads, or stick to raw C++ types instd::threads. - Enable C++11+ in your .pro file: Qt Creator won't enable C++11 by default for older projects. Add this to your
.profile:CONFIG += c++11 # For C++17 features (if needed): # CONFIG += c++17 - Avoid detached threads: Detached threads can outlive your Qt application and cause memory leaks. Always use
join()to wait for threads to finish before destroying their parent objects. - Debug with thread IDs: Use
std::this_thread::get_id()to print thread IDs in critical sections (likeshow_frameand your streamer's run loop) to confirm code is running in the expected threads.
If you still hit issues, add debug logs for every step of the MJPEG pipeline—this will quickly tell you if frames are missing, encoding is failing, or network sends are blocked.
内容的提问来源于stack exchange,提问作者2adnielsenx xx

