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

Erlang中使用Action ID调用wait函数无响应问题求助

问题:Erlang异步模块wait函数无响应,预期结果未返回

重现步骤

  • 在终端执行:
    A1 = async:new(fun(Args) -> lists:seq(1, Args) end, 10).
    
  • 得到输出:"#Ref<0.2297416181.3164864513.214889>"
  • 调用Result = async:wait(A1).后无任何响应,预期结果应为[1,2,3,4,5,6,7,8,9,10]

完整代码

-module(async).
-export([new/2, wait/1, poll/1]).

new(Fun, Arg) ->
    Aid = make_ref(),  % Generate a unique action ID
    ComputationPid = spawn_link(fun() -> execute_computation(self(), Fun, Arg) end),
    State = {ComputationPid, none},
    erlang:put(Aid, State),
    Aid.

execute_computation(ParentPid, Fun, Arg) ->
    try
        Res = Fun(Arg),
        ParentPid ! {self(), {ok, Res}}
    catch
        throw:Ex ->
            ParentPid ! {self(), {exception, Ex}}
    end.

wait(Aid) ->
    receive
        {Aid, {ok, Res}} -> Res;
        {Aid, {exception, Ex}} -> throw(Ex)
    end.

poll(Aid) ->
    State = erlang:get(Aid),
    case State of
        undefined -> nothing;
        {_, none} -> nothing;
        {_, Result} -> Result
    end.

问题原因

  1. 消息格式不匹配:子进程execute_computation发送的消息是{self(), {ok, Res}}(以自身PID为标识),但wait函数等待的是{Aid, ...}(以生成的引用为标识),导致消息无法被正确接收,进程一直阻塞在receive语句。
  2. 进程字典状态未更新:子进程计算完成后,没有将结果写入进程字典,即使消息格式正确,poll函数也无法获取已完成的计算结果。

修复方案

修改代码,使子进程发送包含Aid的消息,并在wait函数中同时处理进程字典的状态检查与消息接收,确保结果能被正确获取:

-module(async).
-export([new/2, wait/1, poll/1]).

new(Fun, Arg) ->
    Aid = make_ref(),
    ComputationPid = spawn_link(fun() -> execute_computation(self(), Aid, Fun, Arg) end),
    State = {ComputationPid, none},
    erlang:put(Aid, State),
    Aid.

execute_computation(ParentPid, Aid, Fun, Arg) ->
    try
        Res = Fun(Arg),
        ParentPid ! {Aid, {ok, Res}}
    catch
        throw:Ex ->
            ParentPid ! {Aid, {exception, Ex}}
    end.

wait(Aid) ->
    case erlang:get(Aid) of
        {_, {ok, Res}} -> Res;
        {_, {exception, Ex}} -> throw(Ex);
        {Pid, none} ->
            receive
                {Aid, {ok, Res}} ->
                    erlang:put(Aid, {Pid, {ok, Res}}),
                    Res;
                {Aid, {exception, Ex}} ->
                    erlang:put(Aid, {Pid, {exception, Ex}}),
                    throw(Ex)
            end;
        undefined ->
            error(invalid_aid)
    end.

poll(Aid) ->
    State = erlang:get(Aid),
    case State of
        undefined -> nothing;
        {_, none} -> nothing;
        {_, Result} -> Result
    end.

修复说明

  • 调整execute_computation的参数,传入Aid,让子进程发送包含Aid的消息,匹配wait的接收格式。
  • 优化wait函数:先检查进程字典中是否已有计算结果,有则直接返回;无则等待消息,收到消息后更新进程字典状态,同时支持poll函数获取结果。
  • 增加无效Aid的错误处理,避免无意义的阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:41:06