Rust threading and channel

I'm experimenting with rust threads and channel for terminating threads. I want the functionality of creating thread in a fucntion and then terminating it from another function. In real, I want to spawn a thread in a fucntion of structure and then terminate it in another function of structure. How can I achieve this?
I created an example as below, but unfortunately I'm not able to send message to sender. Any help on this will be appreciated. I am completely new to rust, any example code to illustrate the functionality will be much appreciated.

use std::thread;
use std::time::Duration;
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};

enum Command {
    Stop
}

fn main() {
    let rx: Receiver<Command> = mpsc::channel().1;
    thread::spawn(move || loop {
        println!("in thread");
        match rx.try_recv() {
            Ok(Command::Stop) => {
                println!("stopping");
                break;
            }
            
            
            Err(_) => {
                println!("continue");
                thread::sleep(Duration::from_secs(1));
            }
            
        }
    });
    
    println!("outside thread");
    thread::sleep(Duration::from_secs(5));
    call_abort();
    println!("after calling abort")
}

fn call_abort() {
    let tx: Sender<Command> = mpsc::channel().0;
    tx.send(Command::Stop);
}

The issue is that your sender and receiver are returned from separate calls to channel(), which means they're not associated in any way. There is no global state with channels, each construction returns a new channel that's only connected to itself.

You should keep both ends of the channel after creating it in a single place:

let (tx, rx) = channel();

and structure things so that your call_abort function can access the original tx.

5 Likes

Okay, got it. I have fixed that issue but now I'm facing an issue with ownership for below code.
here's link for rust playground for same code

use std::thread;
use std::time::Duration;
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};


struct Test {
    sendr : Sender<bool>,
    recvr : Receiver<bool>,
    z: i32
}

impl Test {
    fn new() -> Test{
        let (x, y) = mpsc::channel();
        return Test {
            sendr: x, recvr: y, z: 5
        };
    }
    
    fn recv_func(&mut self, param: i32){
        self.z = param;
        thread::spawn(move || loop {
            match self.recvr.try_recv() {
                Ok(true) | Ok(false) => {
                    println!("in true blcok");
                    thread::sleep(Duration::from_secs(1));
                }
                
                Err(_) => {
                    println!("terminating..");
                    break;
                }
            }    
        });
    }
    
    
    fn send_func(&self){
        self.sendr.send(true);
    }
}

fn main(){
    let mut test = Test::new();
    test.recv_func(4);
    thread::sleep(Duration::from_secs(3));
    test.send_func();
    
    thread::sleep(Duration::from_secs(1));
    
}

You can't move a temporary borrow &mut self into a background thread, perhaps you want to change the field recvr to recvr: Option<Receiver<bool>>, and change the function like this:

    fn recv_func(&mut self, param: i32){
        self.z = param;
        let recvr = self.recvr.take(); // take ownership of the receiver from self to a local
        thread::spawn(move || loop {
            match recvr.try_recv() { // doesn't use self any more
            // rest of the function the same
1 Like

This is exactly what I needed. It works fine with these changes. Thanks a lot @geeklint

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.