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.
问题原因
- 消息格式不匹配:子进程
execute_computation发送的消息是{self(), {ok, Res}}(以自身PID为标识),但wait函数等待的是{Aid, ...}(以生成的引用为标识),导致消息无法被正确接收,进程一直阻塞在receive语句。 - 进程字典状态未更新:子进程计算完成后,没有将结果写入进程字典,即使消息格式正确,
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
相关产品推荐
相关产品推荐

