Есть ли в Эрланге способ, которым отправитель сообщения может дождаться ответа?

StackOverflow https://stackoverflow.com/questions/2312736

  •  22-09-2019
  •  | 
  •  

Вопрос

Есть ли в Erlang какой-либо способ, с помощью которого отправитель сообщения может ждать ответа, чтобы он продолжал выполнение только после того, как сообщение было обработано?

И я имею в виду что-то вроде этого:

Actor ! DoSomething
Continue to this next line of code when DoSomething has been processed

Я знаю, что обратный вызов можно выполнить, отправив Pid отправителя, но есть ли другой способ подождать?

Это было полезно?

Решение

Первое, что нужно понять, это то, что Erlang был создан для асинхронной передачи сообщений.Таким образом, единственный способ обеспечить синхронную передачу сообщений — реализовать что-то вроде подтверждения.

Представьте себе два процесса: P1 и P2.P1 может запустить следующий код:

%% process P1 takes the Pid of P2 as a parameter
%% and a Message to pass on to P2
p1(P2, Message) ->
    P2 ! {self(), Message},
    receive
        {P2, ok}
    after 5000 -> % this section is optional, times out after 5s
        exit("P2 didn't process this!") % this kills P1
    end.

P2 со своей стороны может просто запустить следующее:

p2() ->
    receive
        {From, Message} ->
            io:format("P2 received message ~p~n",[Message]),
            %% processing is done!
            From ! {self(), ok}
    end.

Тогда вы можете создать p2 как новый процесс.Этот будет сидеть и ждать любого сообщения.Когда вы затем вызываете p1, он отправляет сообщение P2, который затем его обрабатывает (io:format/2) и отвечает на P1.Поскольку P1 ждал ответа, внутри этого процесса не запускалось никакого дополнительного кода.

Это основной и единственный способ реализовать блокировку вызовов.Рекомендации по использованию gen_server:call примерно реализовать то, что я только что показал.Однако это скрыто от программиста.

Другие советы

Вы можете использовать получать блокировать:

http://www.erlang.org/doc/reference_manual/expressions.html#id2270724

Чтение из документа:

получить никогда не терпит неудачу.Выполнение приостановлено, возможно, на неопределенное время, пока не появится сообщение, которое соответствует одному из шаблонов и с истинной гвардией.

Другими словами, отправьте сообщение и дождитесь ответа.

Если процесс получения является gen_server, вы можете использовать gen_server:call.Например.:

gen_server:call(Pid, Message),
% At this point, we know that the other process has answered.

Нет, существует только асинхронная передача сообщений.

Если хотите немного пофилософствовать, то очень сложно автоматически определить, когда сообщение было обработано.Это когда сообщение прибыло в процесс, было получено, но еще не обработано, или когда оно было обработано принимающим процессом.Это похоже на получение автоматического уведомления, когда кто-то «прочитал» мою почту.Да, они это видели, но они действительно это читали?

Просто зависит от ситуации jldupont.Если веб-браузер отправляет запрос веб-машине на какой-то долго работающий ресурс erlang, невозможно использовать приведение для выполнения этого запроса.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top