Task.start Elixir中的怪异行为

时间:2018-09-29 00:41:47

标签: erlang elixir task distributed-computing distributed

我正在尝试使用GenServer在Elixir中编写一个八卦模拟器。我有一个main()方法,它充当创建网络拓扑的客户端并启动所有参与者(GenServer的)。然后,它将Genserver.cast()发送给Actor以启动八卦。演员在其handle_cast()中开始Task.start(),开始与其他演员闲聊。似乎我没有以正确的方式使用Task.start()(actor.ex中的第16行),因为从未执行被调用的任务startGossiping()Task.start()之后的语句。混合只是退出而不会给出任何错误。缩短的程序在下面给出。

actor.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

更新: 还没有找出问题所在。我实际上无法启动任何并发过程。 spawnstart_linkTask都没有启动异步任务。

1 个答案:

答案 0 :(得分:0)

GenServer.cast/3Task.start/1都不会阻止您的应用程序退出。

我不确定为什么要构建一个escript来测试代码。您可以使用以下选项等待执行完成再退出(包括但不限于):

•使用mix run --no-halt

•创建一个Application

•启动链接的任务,并在代码中的某处使用Task.await/2等待任务完成。