2013-11-15 133 views
0

是否有可能阻止同步函數(handle_call)等待不同模塊中的異步調用(handle_cast)?erlang混合同步和異步函數

即 如何才能使同步功能等待(即阻止),直到收到來自異步功能的特定「完成」消息? (然後才繼續執行) 這兩個模塊都遵循gen_server和gen_fsm行爲。

handle_info可以以某種方式使用嗎?

問候 /彼得

回答

5

這樣做是爲了節省掉參考發件人handle_call,並在以後調用gen_server:reply的方式。也就是說,當你通常寫你handle_call功能是這樣的:

handle_call(foo, _From, State) -> 
    {reply, {ok, bar}, State}. 

你會做這樣的事情:

handle_call(foo, From, State = #state{pending = Pending}) -> 
    NewState = State#state{pending = [From | Pending]}, 
    {noreply, NewState}. 

再後來,也許在handle_info

handle_info({bar_event, Data}, State = #state{pending = [Head | Tail]) -> 
    gen_server:reply(Head, {ok, Data}), 
    NewState = State#state{pending = Tail}, 
    {noreply, NewState}. 

這意味着當進程調用gen_server:call(Pid, foo)時,它將阻塞,直到服務器進程收到{bar_event, Data},此時服務器將把事件中包含的數據返回給調用者。

我試圖通過在「堆棧」中存儲關於調用者的信息來簡化示例,因此在多個併發調用者的情況下,最後的調用者將首先返回,反之亦然。在很多情況下,您需要使用某種類型的鍵保存來電者信息,以便在獲得異步事件時查找。

這也可以在gen_fsm進程中完成;函數調用和返回值是相似的。

+0

謝謝!這正是我需要的。我完全忘了{noreply,...}「迴歸」。 – peitur

+1

要小心這樣做,因爲'gen_server:call'具有5秒的內置超時,之後會自動生成一個錯誤。超時的長度可以用第三個參數設置,無論是millisecs還是'infinity'。 – rvirding

+0

是的,我在之前的應用程序中遇到過這個問題。現在我通常會設置無窮大或者傳遞一個超時值(用於回調)。這確實使事情有點「凌亂」,儘管:( – peitur