Nano Hash - криптовалюты, майнинг, программирование

Получение пользовательского ввода в задаче эликсира

Я пытаюсь написать простую программу-эликсир, способную реагировать на ввод пользователя. Моя проблема в том, что чтение из stdio не работает из Tasks. Если вся моя идея глупа, пожалуйста, покажите мне пример того, как это делается. ничего не могу найти в сети

Я разбил свою проблему на простой пример:

t = Task.async((fn->IO.gets "what?" end))                
%Task{owner: #PID<0.65.0>, pid: #PID<0.80.0>, ref: #Reference<0.0.2.135>}

Задача запущена:

iex(4)> pid=Map.get(t, :pid)
#PID<0.80.0>
iex(5)> Process.alive? pid                                       
true 

и жив, но не печатает на stdio и не читает. Он не завершается нормально или с исключением. Я тоже пробовал IO.read/2.

В моей программе Task запускается с помощью Task.spawn_link/1, но проблема та же самая.IO.gets/2, и код, следующий за функцией IO.gets/2, не выполняется.

Супервайзер, начинающий задание:

defmodule Prime do
  use Application

    def start(_type, _args) do
       import Supervisor.Spec, warn: false

children = [
  # Define workers and child supervisors to be supervised
  worker(Task, [fn->Prime.IO.communicate(nil) end], restart: :transient),
  supervisor(Prime.Test.Supervisor, [])
]

opts = [strategy: :one_for_one, name: Prime.Supervisor]
Supervisor.start_link(children, opts) end end

Функции задач:

defmodule Prime.IO do

@doc """
    handles communication with the user and user demanded Actions.
"""

def communicate(numTasks) do
    case(numTasks) do

    nil ->
        {numTasks, _} =Integer.parse(IO.gets "This program searches for prime numbers per try and error.\nHow many concurrent Tasks?\n")
        Prime.IO.communicate(numTasks)

    x when is_number(x) ->
        Prime.Test.Server.setTaskNumber(numTasks)
        Prime.IO.communicate("waiting")

    y when is_bitstring(y) ->
        IO.puts(numTasks)

    _ -> 
        Prime.IO.communicate(nil)

    end
end
end 
04.04.2016

Ответы:


1

В Эликсире всегда есть один процесс, обрабатывающий io. Если вы печатаете что-то в одном из процессов, это напрямую не пишется в стандартный вывод. Он отправляет сообщение процессу под названием «лидер группы». Даже если многие процессы пишут одновременно, вы не увидите перепутанных сообщений, как это:

This is This is message one
message two

Вы всегда будете получать чистый вывод:

This is message one
This is message two

В случае ввода может быть только один процесс, читающий со стандартного ввода. Если вы используете сеанс iex, это процесс оболочки. Если другие процессы хотят читать со стандартного ввода, они терпеливо ждут, пока iex не откажется от контроля над стандартным вводом.

Вот почему, если вы вызываете Task.await, функция волшебным образом работает. Это не потому, что await запускает процесс. Await под капотом вызывает receive, который приостанавливает вызвавший его процесс до тех пор, пока не придет сообщение. Shell отказывается от стандартного ввода, и теперь его могут использовать другие процессы, поэтому вы видите подсказку.

По умолчанию await ожидает результатов 5 секунд, так что вам нужно действовать быстро.

Все эти проблемы просто потому, что вы запускаете интерактивный сеанс. Если вы запустите его нормально, все должно просто работать. Когда вы ждете задачи, вы можете указать бесконечный тайм-аут следующим образом:

result = Task.await(t, :infinity)

Это не задокументировано в официальных Task документах, но почти все тайм-ауты OTP соблюдают соглашение о передаче бесконечности как атома.

04.04.2016
  • Большое спасибо за помощь, которую вы указали мне в правильном направлении. Я думаю, что не могу использовать Task.await, так как моя задача в программе порождается под деревом наблюдения, но мне удалось решить ее, приостановив мой первоначальный процесс с помощью :timer.sleep(:infinity) 05.04.2016

  • 2

    Это минимальный код, который будет работать:

    t = Task.async(fn -> IO.gets "What?" end)
    Task.await(t)
    

    В основном вам нужно await возвращенную задачу. Подробнее об асинхронности и ожидании читайте в в Task.await/2 документации.

    04.04.2016
  • спасибо за вашу помощь и за исправление моей ужасной орфографии :) 05.04.2016
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..