erlang - Task.start Elixir 中的奇怪行为
问题描述
我正在尝试使用 GenServer 在 Elixir 中编写一个八卦模拟器。我有一个 main() 方法,它充当创建网络拓扑的客户端并启动所有参与者(GenServer 的)。然后它向Genserver.cast()
一个 Actor 发送一个来发起八卦。演员handle_cast()
开始Task.start()
与其他演员八卦。看起来我没有以Task.start()
正确的方式使用(actor.ex 中的第 16 行),因为被调用的任务startGossiping()
永远不会执行,也不会执行Task.start()
. 混合只是退出而不给出任何错误。缩短的程序如下所示。
演员.ex -
defmodule Actor do
use GenServer
def init([nodeId, neighborList, algorithm]) do
inspect "#{nodeId}"
recCount = 1
gossipingTask = 0
{:ok, {nodeId, neighborList, algorithm, recCount, gossipingTask}}#nodeId, neighborList, algorithm, receivedCount
end
def handle_cast({:message, rumour}, state) do
{nodeId, neighborList, algorithm, recCount, gossipingTask} = state
IO.puts "nodeId - #{nodeId} recCount - #{recCount} handle_cast: #{rumour} gossipingTask - #{gossipingTask}"
nL = elem(state, 1)
IO.puts "here #{rumour}"
gossipingTask = Task.start(fn -> startGossiping(nL, rumour) end)
IO.puts "Now again - #{rumour}"
{:noreply, {nodeId, neighborList, algorithm, recCount + 1, gossipingTask}}
end
def startGossiping(nL, rumour) do
IO.puts "In startGossiping "
#{Enum.random(nL)}"
# GenServer.cast(Proj2.intToAtom(Enum.random(nL)), {:message, rumour})
end
end
proj2.ex -
defmodule Proj2 do
# Instructions to run the project
# 1) $mix escript.build
# 2) $escript proj2 100 full gossip
def main(args) do
# Receive total number of nodes, topology, algorithm, triggerNodes(optional), threshold(optional) from user.
# Read README.md for more details
numOfNodes = String.to_integer(Enum.at(args, 0))
topology = Enum.at(args, 1)
algorithm = Enum.at(args, 2)
numOfNodes = if String.contains?(topology, "2d"), do: round(:math.pow(round(:math.sqrt(numOfNodes)), 2)), else: numOfNodes
case topology do
"full" ->
Enum.each 1..numOfNodes, fn nodeId ->
neighborList = getNeighborsFull(nodeId, numOfNodes)
inspect neighborList
nodeId_atom = intToAtom(nodeId)
GenServer.start_link(Actor, [nodeId, neighborList, algorithm], name: nodeId_atom)
# IO.puts "In main, nodeId = #{nodeId}"
end
end
GenServer.cast(intToAtom(2), {:message, "This is Elixir Gossip Simulator"})
end
def getNeighborsFull(nodeId,numOfNodes) do
range = 1..numOfNodes
range
|> Enum.filter(fn(value) -> value != nodeId end)
|> Enum.map(fn(filtered_value) -> filtered_value * 1 end)
# IO.inspect Neighboringlist
end
def intToAtom(integer) do
integer |> Integer.to_string() |> String.to_atom()
end
end
更新:还没有弄清楚问题所在。我实际上无法启动任何并发进程。spawn
, start_link
,Task
他们都没有启动异步任务。
解决方案
也GenServer.cast/3
不会Task.start/1
阻止您的应用程序退出。
我不确定你为什么要构建一个escript
来测试代码。您有以下选项等待执行完成后再退出(包括但不限于):
• 创建一个Application
• 启动链接的任务并使用Task.await/2
代码中的某处等待任务完成。
推荐阅读
- java - LDAP Java 打印调试输出
- php - 如何在 laravel 中创建动态选择选项 chantiers ouvrages?
- perl - 在 perl 中将哈希推入数组,结果无法理解
- java - 创建一个简单的应用程序,无法获得清晰的按钮来工作
- java - 如何比较 Java 中三个数组列表的大小?
- filter - 如何在添加自定义过滤器选项中编辑 Odoo 11 中的过滤器和字段
- python - 包含所有组合列表的功能
- r - 在 2 列 Dataframe 上应用 API 函数,输出第三列
- jmeter - 是否必须在 HTTP 请求默认值中检查“检索所有嵌入式资源”以进行性能测试?
- java - Spark结构化流:为什么java代码使用DataSet而scala使用DataFrame类型?