【发布时间】:2015-04-18 15:34:30
【问题描述】:
例如假设我有一个实现 gen_server 行为的模块,它有
handle_call({foo, Foo}, _From, State) ->
{reply, result(Foo), State}
;
我可以通过从其他进程执行 gen_server:call(Server, {foo, Foo}) 来访问此处理程序(我猜如果 gen_server 尝试 gen_server:call 本身,它会死锁)。但是 gen_server:call 响应(或超时)阻塞。如果我不想阻止响应怎么办?
虚构的用例:假设我有 5 个这样的 gen_server,并且来自其中任何 2 个的响应对我来说就足够了。我想做的是这样的:
OnResponse -> fun(Response) ->
% blah
end,
lists:foreach(
fun(S) ->
gen_server:async_call(S, {foo, Foo}, OnResponse)
end,
Servers),
Result = wait_for_two_responses(Timeout),
lol_i_dunno()
我知道 gen_server 有强制转换,但是强制转换无法提供任何响应,所以我认为这不是我想要的。此外,调用者是否希望同步处理响应(使用 gen_server:call)或异步(似乎不存在?)似乎不应该是 gen_server 的关注点。
此外,允许服务器提供异步响应,方法是让 handle_call 返回 no_reply,然后调用 gen_server:reply。那么为什么不在另一边也支持异步处理响应呢?还是确实存在,只是我没找到??
【问题讨论】:
-
这不是
handle_cast的用途吗? -
哦,我看到你在问题中提到了 cast,但那是异步方式。如果其他进程需要响应,则服务器需要发送另一条异步消息。
-
如果你打算通过 handle_cast 异步发送响应,那么整个 gen_server 似乎是没用的,因为你最终需要在 cast 中发送 sender。 handle_call 不应该关心其他进程是否阻塞响应。我的意思是,我可以启动一个新进程将同步调用变为异步调用,但这似乎很浪费。
-
我认为您不需要一个新进程来使其异步。看起来您已经在传递一个回调函数。我没有足够的 erlang 经验来提供更多帮助,但我知道
handle_call用于同步方法,handle_cast用于异步。将消息发送回发件人是进行异步的完美方式。不要与之抗争。
标签: erlang erlang-otp