You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中线程生成后衍生函数未执行的问题排查与解决

问题

我设计的TCP服务器打算用多个线程处理流,但运行时线程里的函数完全没执行,服务器无报错直接退出。以下是最小复现代码:

use std::net::{TcpListener, TcpStream};
use std::thread;
use std::env::{args, Args};

fn handle_client(mut stream: TcpStream) {}

fn handle_streams(listener: &TcpListener) {
   for stream in listener.incoming() {
      match stream {
         Ok(stream) => {
            handle_client(stream);
         }
         Err(e) => {
            eprintln!("connecting fail, cause: {}", e);
         }
      }
   }
}

fn main() -> () {
    let arguments: Args = args();
    let arguments_string_vector: Vec<String> =  arguments.collect();
    let listener_ip_address: &String = arguments_string_vector.get(1).unwrap();
    let listener_port: &String = arguments_string_vector.get(2).unwrap();
    let listener_address = format!("{}:{}", listener_ip_address, listener_port);
    let listener_bind_error_message = format!("bind fail on {}", listener_address);
    let listener = TcpListener::bind(listener_address.clone())
        .expect(&listener_bind_error_message);
    println!("listening on {}", listener_address);

    let threads_demand_quantity_string: &String = arguments_string_vector.get(5).unwrap();
    let threads_demand_quantity: u32 = threads_demand_quantity_string.parse().expect("threads demand not defined");
    for _i in 1..=threads_demand_quantity {
        let listener_clone = listener.try_clone().unwrap();
        thread::spawn( move || {
            handle_streams(&listener_clone);
        });
    }
}

问题出在这段代码:

for _i in 1..=threads_demand_quantity {
   let listener_clone = listener.try_clone().unwrap();
   thread::spawn( move || {
      handle_streams(&listener_clone);
   });
}

我测试过以下类似代码能正常运行:

use std::thread;
use std::time::Duration;

fn main() -> () {
   for _i in 1..=10 {
       thread::spawn( move ||
           {
               println!("thread");
               thread::sleep(Duration::new(3, 0))
           }
       );
   }
}

以及:

use std::thread;

fn secondary(arg: &str) {println!("{}",arg)}

fn main() -> () {
   for _i in 1..=10 {
       thread::spawn( move ||
           {
               println!("thread {}", _i);
               secondary(&"arg")
           }
       );
   }
}

请问如何修复让线程里的函数正常执行?

解决方案

问题核心是主线程执行完毕后会直接退出,所有子线程会被强制终止。Rust中thread::spawn创建的是后台线程,主线程结束时不会等待这些子线程完成。你测试的两段代码看似正常,其实是因为thread::sleep让子线程存活时间足够长,主线程退出前能看到输出,但本质上主线程退出后子线程还是会被杀死。

修复方法有两种,按需选择:

方法1:让主线程等待所有子线程完成

收集每个线程的JoinHandle,在main函数末尾调用join()等待所有线程结束:

修改main函数的循环部分:

let mut handles = Vec::new();
for _i in 1..=threads_demand_quantity {
    let listener_clone = listener.try_clone().unwrap();
    let handle = thread::spawn(move || {
        handle_streams(&listener_clone);
    });
    handles.push(handle);
}

// 等待所有线程完成
for handle in handles {
    handle.join().unwrap();
}

这样主线程会一直阻塞,直到所有子线程结束(比如服务器停止监听)。

方法2:让主线程无限运行(适合服务器场景)

如果服务器需要一直运行,不需要等待子线程结束(因为子线程会一直监听连接),可以让主线程进入无限循环:

在main函数末尾添加:

// 主线程无限休眠,保持进程存活
loop {
    std::thread::sleep(std::time::Duration::from_secs(86400));
}

或者用更轻量的方式,比如等待标准输入:

// 等待用户输入任意内容再退出
std::io::stdin().read_line(&mut String::new()).unwrap();

两种方法都能保证子线程有机会执行handle_streams里的逻辑,不会因为主线程提前退出而被终止。

内容的提问来源于stack exchange,提问作者Dimon agon IO_04

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 14:55:55