Странное поведение в Task.start Elixir - PullRequest
0 голосов
/ 29 сентября 2018

Я пытаюсь написать симулятор сплетен на эликсире, используя GenServer.У меня есть метод main (), который действует как клиент, создающий топологию сети и запускающий всех участников (GenServer's).Затем он посылает Genserver.cast() Актеру, чтобы инициировать сплетни.Актер в своем handle_cast() начинает Task.start(), чтобы начать сплетничать с другими актерами.Похоже, я не правильно использую Task.start() (строка 16 в actor.ex), поскольку вызываемая задача startGossiping() никогда не выполняется, а операторы после Task.start().Mix просто выходит без каких-либо ошибок.Сокращенная программа приведена ниже.

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

ОБНОВЛЕНИЕ: Проблема еще не выяснена.Я не могу запустить какой-либо параллельный процесс на самом деле.spawn, start_link, Task Ни один из них не запускает асинхронную задачу.

1 Ответ

0 голосов
/ 29 сентября 2018

Ни GenServer.cast/3, ни Task.start/1 не будут препятствовать выходу из приложения.

Я не уверен, зачем вам создавать escript для проверки кода.У вас есть следующие варианты, чтобы дождаться завершения выполнения перед выходом (включая, но не ограничиваясь):

• использовать mix run --no-halt

• создать Application

• запустите связанную задачу и используйте Task.await/2 где-нибудь в своем коде, чтобы дождаться завершения задачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...