0

I am trying to send some data between two threads but it is taking upwards of 5-10 seconds for it to be received on the other thread. The main thread is running a GUI (written in egui), and when the user clicks a button, it spawns the second thread, creating an MPSC channel in the process. The second thread opens an camera and tries to decode a QR code using openCV, and if it detects a string length of greater than zero, it sends that back to the main thread. The main thread then drops its end of the channel, which causes the other thread to end.

I have set up a 'heartbeat' message which comes through in under a second, but whenever I actually detect a QR code and send the string, it takes ages to come through to the other thread. All the output pauses, I get multiple instances of it 'sending' the string, but no debug output from the main thread saying it received it until 5-10 seconds later.

This is my code running in the second thread, the one that seems to get all of the cpu time (I also tried it with it creating a openCV window and showing the output, and that continued to update fast, so that thread was still running fine) :

pub enum QRThreadResponse {
    NewQRString(String),
    ThreadError(String),
    Heartbeat,
    ThreadShutdown,
}


pub fn SpawnQrThread(camera_id: i32, chl: Sender<QRThreadResponse>){
    thread::spawn(move || {
        println!("Hello from QR Thread");
        let mut qr_detector = objdetect::QRCodeDetector::default().expect("FAILED to create QR Detector");
        let mut res = types::VectorOfPoint::new();
        let mut camera = videoio::VideoCapture::new(camera_id, videoio::CAP_DSHOW).expect("Open Camera Failed");
        let mut img = Mat::default();
        let mut recqr = Mat::default();

        loop{
            match camera.read(&mut img) {
                Err(_) => break,
                _ => (),
            };
            let ret = qr_detector.detect_and_decode(&img, &mut res, &mut recqr).expect("QR DETECT ERROR");
            let s = String::from_utf8_lossy(&ret);
            if s.len() > 0 {
                println!("SENDING: {:?}", s);
                match chl.send(QRThreadResponse::NewQRString(s.to_string())){
                    Err(_) => {println!("QUITTING QR THREAD NQS"); break},
                    _ => (),
                }
            }

            match chl.send(QRThreadResponse::Heartbeat){
                Err(_) => {println!("QUITTING QR THREAD HB"); break},
                _ => (),
            }
        }

    });
    ()
}

In my main GUI thread, I simply call this function when the button is pressed:

    fn spawn_camera_thread(&mut self) {
        if self.QRRecieveThread.is_none() {
            let (snd, rcv) = channel();
            SpawnQrThread(0, snd);
            self.QRRecieveThread = Some(rcv);
        }
    }

And in the GUI thread I check for a response:

if let Some(qr_thread) = &self.QRRecieveThread{
    if let Ok(qr_response) = qr_thread.recv_timeout(Duration::from_millis(1)) {
        match qr_response {
            QRThreadResponse::NewQRString(data) => {
                self.update_activity_log(data);
                self.app_state = AppState::NewItemScanned;
                self.kill_qr_thread();
            },
            QRThreadResponse::Heartbeat => println!("Got Heartbeat"),
            _ => (),
        }
    }
}

How do I figure out why its taking so long for data to be sent between the threads? Could this just be a result of the openCV bindings and the underlying C++ code not sharing the thread time?

I have tried this in Debug and release mode, no change.

birdistheword99
  • 179
  • 1
  • 15
  • 3
    You should create a minimal reproducible example. That would definitively help you identifying the bug; and that would definitively help us help you, as currently unless someone has already seen this specific issue and knows how to solve it, it's pretty hard to do anything. – jthulhu Aug 17 '23 at 09:17

0 Answers0