Erlang 使用动作 id,等待功能不起作用

Erlang using action id, wait function is not working

提问人:Arraytics New 提问时间:10/3/2023 最后编辑:Steve VinoskiArraytics New 更新时间:10/3/2023 访问量:36

问:

我只是尝试在终端中运行一个简单的函数:

A1 = async:new(fun(Args) -> lists:seq(1, Args) end, 10).

它显示的输出如下:但是当我尝试运行该函数时,它不起作用并且不显示任何内容。我期待得到这样的结果。"#Ref<0.2297416181.3164864513.214889>"wait[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.

此行已添加到终端中,但未显示任何内容:

Result = async:wait(A1).
异常 try-catch throw erlang-otp

评论


答:

0赞 Steve Vinoski 10/3/2023 #1

主要问题是你混淆了引用和 pid。在函数中,使用 pid 作为元组的第一个元素发送消息:execute_computation/3

    ParentPid ! {self(), {ok, Res}}

但是在函数中,您尝试接收以引用为第一个元素的元组:wait/1

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

另一个问题是,当您生成调用时,您尝试传递父 pid,但其中的调用是生成进程的 pid,而不是父进程。execute_computation/3self()fun

要修复它,首先,通过传递父 pid 并传递引用来更改生成调用的方式:execute_computation/3

    Self = self(),
    ComputationPid = spawn_link(fun() -> execute_computation(Self, Aid, Fun, Arg) end),

接下来,修复函数以接受 4 个参数,并将引用包含在发送的元组中:execute_computation

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

最后,修复以接收正确的元组:wait/1

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

请注意,您似乎没有使用元组中传递的进程的 pid,因此您可以考虑删除它。execute_computation/3

通过这些更改,一切将按预期进行:

2> A1 = async:new(fun(Args) -> lists:seq(1, Args) end, 10).
#Ref<0.942710366.4246732815.239328>
3> async:wait(A1).
[1,2,3,4,5,6,7,8,9,10]

评论

0赞 Arraytics New 10/4/2023
是的,它运行良好。多谢。我一直在为这个 ParentPid 和自我部分而苦苦挣扎,你正确地解释了它,现在我的概念很清楚了。:)