Power of Elixir 태스크 모듈 - 시작

10635 단어 elixirasynctask
최근에 나는 Elixir Task 모듈이 어떻게 작동하는지 더 깊이 연구하고 있었고 내 연구를 통합하기 위해 이 포스트를 쓰기로 결정했습니다.

시작하기 전에 Task 모듈의 정의를 확인합시다. 가장 좋은 곳은 Elixir 공식 문서에 있습니다. 우리는 다음을 가지고 있습니다:

Conveniences for spawning and awaiting tasks.

Tasks are processes meant to execute one particular action throughout their lifetime, often with little or no communication with other processes. The most common use case for tasks is to convert sequential code into concurrent code by computing a value asynchronously



좋은 정의지만 코드를 보여주세요!!

비동기 작업 시작


Task 를 사용하여 비동기 작업을 실행하는 두 가지 기본 방법이 있습니다. Task.startTask.async 를 사용할 수 있습니다. 어떻게 작동하는지 봅시다.

작업 시작

Task.start(fn -> IO.inspect("Hello") end)



{:ok, #PID<0.114.0>}


작업.비동기

Task.async(fn -> IO.inspect("Hello") end)



%Task{
  owner: #PID<0.110.0>,
  pid: #PID<0.118.0>,
  ref: #Reference<0.626386777.2138832899.106529>
}

Task.start:ok 및 프로세스 ID가 있는 튜플을 반환하고 Task.async는 Task 구조체를 반환하는 것을 볼 수 있습니다. 그러나 둘 다 같은 방식으로 작동합니다.

때로는 다음 단계를 실행하기 위해 일부 비동기 프로세스 결과를 기다려야 합니다. 하자!

결과를 기다리는 중



이전 샘플은 매우 기본적이었습니다. 약간의 지연을 추가하면 더 좋아질 것입니다.

  Task.async(fn ->
    :timer.sleep(5000)
    IO.inspect("Hello")
    :ok
  end)


알다시피 응답은 %Task{} 구조체입니다. 응답을 기다리기 위해 Task.awaitTask. yield 두 가지 옵션이 있습니다. 차이점을 확인해 보겠습니다.

작업 대기
  • 기본 시간 초과는 5초입니다.
  • 시간 초과가 발생하면 예외가 발생합니다.
  • 시간 초과에 도달하면 작업이 중지됩니다.
  • 사용자 지정 시간 초과를 정의하거나 원자를 사용할 수 있습니다:infinity.

  • Task.await(task)
    Task.await(task, :infinity)
    


    시간 초과 샘플

    > task = Task.async(fn -> IO.inspect("Hello") ; :timer.sleep(10000); :ok end)
    
    > Task.await(task)
    "Hello"
    ** (exit) exited in: Task.await(%Task{owner: #PID<0.110.0>, pid: #PID<0.124.0>, ref: #Reference<0.3761442499.262406148.76432>}, 5000)
        ** (EXIT) time out
        (elixir 1.11.3) lib/task.ex:643: Task.await/2
    


    보시다시피 Task.await 를 사용할 때 시간 초과가 약간 폭발적입니다. 더 잘 처리하는 방법은 Supervised Tasks 을 사용하는 것입니다.

    작업 수율
  • 기본 시간 초과는 5초입니다.
  • 시간 초과가 주어지면 nil 를 반환합니다.
  • 원자:infinity를 사용하는 것은 Task.await에서와 같이 허용되지 않습니다.
  • 시간 초과에 도달한 후 작업을 계속 실행합니다.
  • Task.shutdown(task, shutdown \\ 5000) 를 사용하여 실행 중인 작업을 완료할 수 있습니다.

  • > task = Task.async(fn -> IO.inspect("Hello") ; :timer.sleep(10000); :ok end)
    > Task.yield(task)
    nil
    # Let's check again
    > Task.yield(task)
    {:ok, :ok}
    

    :timeout 결과가 주어지면 응답은 nil 가 됩니다. 그런 다음 Task.yield를 다시 실행할 수 있습니다. 결과가 없는 장기 실행 작업을 방지하려면 Task.shutdown(task, shutdown \\ 5000) 를 사용해야 합니다.

    더 완전한 샘플



    항목 목록이 있으며 모든 항목에서 일부 작업을 실행해야 합니다.

        items = ["alpha", "beta", "gama"]
    
        Enum.map(items, fn item ->
          Task.async(fn ->
            :timer.sleep(4000)
            IO.inspect("Hello #{item}")
            :ok
          end)
        end)
        |> Enum.map(&Task.await/1)
        |> function_to_handle_results()
    


    이 접근 방식을 사용하면 제한 시간에 도달하면 여전히 예외가 발생합니다. 그러나 Supervised Tasks 을 사용하여 더 나은 방법으로 처리할 수 있지만 이 주제는 .

    추가 콘텐츠


  • Elixir Findings: Asynchronous Task Streams
  • The problem with Task.await/2 and timeouts
  • 좋은 웹페이지 즐겨찾기