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

Actix框架中send触发处理但do_send未被处理的原因

Actix do_send 消息未触发处理的认知偏差排查

本次核心诉求为厘清自身对Actix认知模型的疏漏,在此先行致谢。

基础示例代码

消息与响应定义

#[derive(Message)]
#[rtype(result = "Responses")]
enum Messages {Ping,Pong}

#[derive(Debug)]
enum Responses {GotPing,GotPong}

impl<A, M> MessageResponse<A, M> for Responses
where
    A: Actor,
    M: Message<Result = Responses>
{
    fn handle(self, _ctx: &mut A::Context, tx: Option<OneshotSender<M::Result>>) {
        if let Some(tx) = tx {tx.send(self);}
    }
}

main函数实现

#[actix_rt::main]
pub async fn main() {
    let addr           = ActorQuox.start();
    let pongfut_async  = addr.send(Messages::Pong).await;
    pongfut_async.map_or(Responses::GotPong, |res| {
        println!("Got result: {:?}", res);
        res
    });

    let ping  = addr.do_send(Messages::Ping);
}

预期与实际输出不符

预期输出

Got message
Got result: GotPong
Got message

实际输出

Got message
Got result: GotPong

核心认知偏差与成因

此前认知:impl Handler<Messages> for ActorQuox的处理逻辑会对do_send、send、try_send三个方法均触发执行,三者在Addr的实现中都执行了消息投递逻辑,仅返回值签名存在差异。

该认知的偏差点如下:

  1. 三个发送方法确实都会将消息投递到Actor邮箱,Handler也确实会对所有投递成功的消息触发执行,但前提是Actix运行时没有提前终止,给Actor留出处理邮箱消息的时间。
  2. 三个方法的等待逻辑差异是问题核心:
    • send是异步方法,会返回一个Future,await该Future时会暂停当前任务,直到目标Actor处理完对应消息、通过oneshot通道返回响应后才会继续往下执行。示例中addr.send(Messages::Pong).await会等待Pong消息被Actor完整处理(包括打印"Got message"、返回响应),后续的结果打印逻辑也会正常执行。
    • do_send是发后即忘的同步方法,仅负责将消息塞入Actor的邮箱队列就立刻返回,完全不会等待消息被Actor处理。示例中调用完addr.do_send(Messages::Ping)后,main函数直接走到末尾结束,actix_rt运行时会随main函数退出直接关停,此时Ping消息还躺在Actor的邮箱队列里没被取出处理,自然不会输出第三条"Got message"。
    • try_send逻辑和do_send基本一致,唯一区别是当Actor邮箱已满时会直接返回错误,不会阻塞等待入队,同样不会等待消息处理完成。

验证方式

在do_send调用后增加一个短延时,给Actor留出处理消息的时间,就能看到预期的第三条输出:

let ping = addr.do_send(Messages::Ping);
// 增加100ms延时等待运行时处理邮箱内的剩余消息
tokio::time::sleep(std::time::Duration::from_millis(100)).await;

或者将do_send替换为send并await,也能稳定看到Ping消息的处理输出。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:21:22