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

从C调用Rust DLL生成独立线程并释放C主线程的问题

问题分析

你的核心问题出在Rust的spawn_thread_and_get_back函数里:创建新线程后调用了handle.join(),这个方法会阻塞当前的C调用线程,直到新线程执行完成。但新线程里的runForever是带无限循环的Tokio任务,永远不会终止,导致C主线程被死死卡住,根本无法进入后续的while循环。

另外还有一个潜在问题:keep_calling_rust_fn里调用的someRandomPrintTask使用了tokio::spawn,但当前调用线程(C主线程)没有绑定Tokio runtime,直接调用会触发panic,这个也需要一并修复。

修复后的Rust代码
use std::thread;
use std::time::Duration;
use tokio;

async fn counter() {
    loop {
        println!("I am getting called by Tokio every 2 seconds");
        tokio::time::sleep(Duration::from_secs(2)).await;
    }
}

// 手动创建并运行Tokio runtime,避免#[tokio::main]的自动线程阻塞
fn runForever() {
    let rt = tokio::runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let counter_task = tokio::spawn(counter());
        // 无限等待任务(因counter是循环,此处会持续阻塞线程)
        let _ = counter_task.await;
    });
}

#[no_mangle]
pub unsafe extern "C" fn spawn_thread_and_get_back() {
    // 创建后台线程后直接返回,不调用join(),释放C调用线程
    thread::spawn(move || {
        println!("Trying to create new thread for Tokio runtime");
        runForever();
    });
}

#[no_mangle]
pub unsafe extern "C" fn keep_calling_rust_fn() {
    println!("I am getting called by C wrapper every 7 seconds");
    some_random_print_task();
}

async fn print_task(task_number: u32) {
    println!("Print task {} -", task_number);
}

// 手动创建临时Tokio runtime执行异步任务,避免无runtime上下文的panic
fn some_random_print_task() {
    let rt = tokio::runtime::Runtime::new().unwrap();
    rt.block_on(async {
        let print_task = tokio::spawn(print_task(10));
        let _ = print_task.await;
    });
}
关键修改点说明
  • 移除handle.join():这是让C主线程摆脱阻塞的核心。创建后台线程后直接返回,让新线程在后台独立运行无限循环任务,不会阻塞调用它的C线程。
  • 手动管理Tokio Runtime:去掉#[tokio::main]宏,手动创建Runtime并使用block_on运行异步任务,避免宏自动带来的线程阻塞问题。
  • 修复异步任务的Runtime上下文问题:C主线程没有Tokio Runtime环境,直接调用tokio::spawn会panic,因此在some_random_print_task里手动创建临时Runtime执行异步逻辑。
  • 明确使用Tokio的sleep:替换原代码中未指定来源的sleep为tokio::time::sleep,确保异步任务的非阻塞特性符合预期。
补充C代码优化建议

原C代码的while循环没有sleep逻辑,会疯狂调用keep_calling_rust_fn,和注释里的“每7秒调用”不符,建议添加sleep并修正输出刷新问题:

while(1){
    printf("Calling rust function\n"); // 加换行符确保输出即时刷新
    keep_calling_rust_fn();
    sleep(sleep_seconds); // 实现每7秒调用一次的逻辑
}

内容的提问来源于stack exchange,提问作者p_b

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 00:55:05