<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="generator" content="ExDoc v0.19.1"> <title>Task – Elixir v1.7.2</title> <link rel="stylesheet" href="dist/app-240d7fc7e5.css" /> <link rel="canonical" href="https://hexdocs.pm/elixir/v1.7/Task.html" /> <script src="dist/sidebar_items-cdf4e58b19.js"></script> </head> <body data-type="modules"> <script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script> <div class="main"> <button class="sidebar-button sidebar-toggle"> <span class="icon-menu" aria-hidden="true"></span> <span class="sr-only">Toggle Sidebar</span> </button> <button class="sidebar-button night-mode-toggle"> <span class="icon-theme" aria-hidden="true"></span> <span class="sr-only">Toggle Theme</span> </button> <section class="sidebar"> <a href="http://elixir-lang.org/docs.html" class="sidebar-projectLink"> <div class="sidebar-projectDetails"> <h1 class="sidebar-projectName"> Elixir </h1> <h2 class="sidebar-projectVersion"> v1.7.2 </h2> </div> <img src="assets/logo.png" alt="Elixir" class="sidebar-projectImage"> </a> <form class="sidebar-search" action="search.html"> <button type="submit" class="search-button"> <span class="icon-search" aria-hidden="true"></span> </button> <input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" /> </form> <ul class="sidebar-listNav"> <li><a id="extras-list" href="#full-list">Pages</a></li> <li><a id="modules-list" href="#full-list">Modules</a></li> <li><a id="exceptions-list" href="#full-list">Exceptions</a></li> </ul> <div class="gradient"></div> <ul id="full-list" class="sidebar-fullList"></ul> </section> <section class="content"> <div class="content-outer"> <div id="content" class="content-inner"> <h1> <small class="visible-xs">Elixir v1.7.2</small> Task <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L1" title="View Source" class="view-source" rel="help"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> </h1> <section id="moduledoc"> <p>Conveniences for spawning and awaiting tasks.</p> <p>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:</p> <pre><code class="nohighlight makeup elixir"><span class="n">task</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">async</span><span class="p" data-group-id="5467738386-1">(</span><span class="k" data-group-id="5467738386-2">fn</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">do_some_work</span><span class="p" data-group-id="5467738386-3">(</span><span class="p" data-group-id="5467738386-3">)</span><span class="w"> </span><span class="k" data-group-id="5467738386-2">end</span><span class="p" data-group-id="5467738386-1">)</span><span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">do_some_other_work</span><span class="p" data-group-id="5467738386-4">(</span><span class="p" data-group-id="5467738386-4">)</span><span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">await</span><span class="p" data-group-id="5467738386-5">(</span><span class="n">task</span><span class="p" data-group-id="5467738386-5">)</span></code></pre> <p>Tasks spawned with <code class="inline">async</code> can be awaited on by their caller process (and only their caller) as shown in the example above. They are implemented by spawning a process that sends a message to the caller once the given computation is performed.</p> <p>Besides <a href="#async/1"><code class="inline">async/1</code></a> and <a href="#await/2"><code class="inline">await/2</code></a>, tasks can also be started as part of a supervision tree and dynamically spawned on remote nodes. We will explore all three scenarios next.</p> <h2 id="module-async-and-await" class="section-heading"> <a href="#module-async-and-await" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> async and await </h2> <p>One of the common uses of tasks is to convert sequential code into concurrent code with <a href="Task.html#async/1"><code class="inline">Task.async/1</code></a> while keeping its semantics. When invoked, a new process will be created, linked and monitored by the caller. Once the task action finishes, a message will be sent to the caller with the result.</p> <p><a href="Task.html#await/2"><code class="inline">Task.await/2</code></a> is used to read the message sent by the task.</p> <p>There are two important things to consider when using <code class="inline">async</code>:</p> <ol> <li><p>If you are using async tasks, you <strong>must await</strong> a reply as they are <em>always</em> sent. If you are not expecting a reply, consider using <a href="Task.html#start_link/1"><code class="inline">Task.start_link/1</code></a> detailed below.</p> </li> <li><p>async tasks link the caller and the spawned process. This means that, if the caller crashes, the task will crash too and vice-versa. This is on purpose: if the process meant to receive the result no longer exists, there is no purpose in completing the computation.</p> <p> If this is not desired, use <a href="Task.html#start/1"><code class="inline">Task.start/1</code></a> or consider starting the task under a <a href="Task.Supervisor.html"><code class="inline">Task.Supervisor</code></a> using <code class="inline">async_nolink</code> or <code class="inline">start_child</code>.</p> </li> </ol> <p><a href="Task.html#yield/2"><code class="inline">Task.yield/2</code></a> is an alternative to <a href="#await/2"><code class="inline">await/2</code></a> where the caller will temporarily block, waiting until the task replies or crashes. If the result does not arrive within the timeout, it can be called again at a later moment. This allows checking for the result of a task multiple times. If a reply does not arrive within the desired time, <a href="Task.html#shutdown/2"><code class="inline">Task.shutdown/2</code></a> can be used to stop the task.</p> <h2 id="module-supervised-tasks" class="section-heading"> <a href="#module-supervised-tasks" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Supervised tasks </h2> <p>It is also possible to spawn a task under a supervisor. The <a href="Task.html#content"><code class="inline">Task</code></a> module implements the <a href="#child_spec/1"><code class="inline">child_spec/1</code></a> function, which allows it to be started directly under a supervisor by passing a tuple with a function to run:</p> <pre><code class="nohighlight makeup elixir"><span class="nc">Supervisor</span><span class="o">.</span><span class="n">start_link</span><span class="p" data-group-id="9494161901-1">(</span><span class="p" data-group-id="9494161901-2">[</span><span class="w"> </span><span class="p" data-group-id="9494161901-3">{</span><span class="nc">Task</span><span class="p">,</span><span class="w"> </span><span class="k" data-group-id="9494161901-4">fn</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">...</span><span class="w"> </span><span class="n">some</span><span class="w"> </span><span class="n">function</span><span class="w"> </span><span class="n">...</span><span class="w"> </span><span class="k" data-group-id="9494161901-4">end</span><span class="p" data-group-id="9494161901-3">}</span><span class="w"> </span><span class="p" data-group-id="9494161901-2">]</span><span class="p" data-group-id="9494161901-1">)</span></code></pre> <p>However, if you want to invoke a specific module, function and arguments, or give the task process a name, you need to define the task in its own module:</p> <pre><code class="nohighlight makeup elixir"><span class="kd">defmodule</span><span class="w"> </span><span class="nc">MyTask</span><span class="w"> </span><span class="k" data-group-id="6841304444-1">do</span><span class="w"> </span><span class="kn">use</span><span class="w"> </span><span class="nc">Task</span><span class="w"> </span><span class="kd">def</span><span class="w"> </span><span class="nf">start_link</span><span class="p" data-group-id="6841304444-2">(</span><span class="n">arg</span><span class="p" data-group-id="6841304444-2">)</span><span class="w"> </span><span class="k" data-group-id="6841304444-3">do</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">start_link</span><span class="p" data-group-id="6841304444-4">(</span><span class="bp">__MODULE__</span><span class="p">,</span><span class="w"> </span><span class="ss">:run</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="6841304444-5">[</span><span class="n">arg</span><span class="p" data-group-id="6841304444-5">]</span><span class="p" data-group-id="6841304444-4">)</span><span class="w"> </span><span class="k" data-group-id="6841304444-3">end</span><span class="w"> </span><span class="kd">def</span><span class="w"> </span><span class="nf">run</span><span class="p" data-group-id="6841304444-6">(</span><span class="n">arg</span><span class="p" data-group-id="6841304444-6">)</span><span class="w"> </span><span class="k" data-group-id="6841304444-7">do</span><span class="w"> </span><span class="c1"># ...</span><span class="w"> </span><span class="k" data-group-id="6841304444-7">end</span><span class="w"> </span><span class="k" data-group-id="6841304444-1">end</span></code></pre> <p>And then passing it to the supervisor:</p> <pre><code class="nohighlight makeup elixir"><span class="nc">Supervisor</span><span class="o">.</span><span class="n">start_link</span><span class="p" data-group-id="1470901559-1">(</span><span class="p" data-group-id="1470901559-2">[</span><span class="w"> </span><span class="p" data-group-id="1470901559-3">{</span><span class="nc">MyTask</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p" data-group-id="1470901559-3">}</span><span class="w"> </span><span class="p" data-group-id="1470901559-2">]</span><span class="p" data-group-id="1470901559-1">)</span></code></pre> <p>Since these tasks are supervised and not directly linked to the caller, they cannot be awaited on. Note <a href="#start_link/1"><code class="inline">start_link/1</code></a>, unlike <a href="#async/1"><code class="inline">async/1</code></a>, returns <code class="inline">{:ok, pid}</code> (which is the result expected by supervisors).</p> <p>Note <code class="inline">use Task</code> defines a <a href="#child_spec/1"><code class="inline">child_spec/1</code></a> function, allowing the defined module to be put under a supervision tree. The generated <a href="#child_spec/1"><code class="inline">child_spec/1</code></a> can be customized with the following options:</p> <ul> <li><code class="inline">:id</code> - the child specification identifier, defaults to the current module </li> <li><code class="inline">:start</code> - how to start the child process (defaults to calling <code class="inline">__MODULE__.start_link/1</code>) </li> <li><code class="inline">:restart</code> - when the child should be restarted, defaults to <code class="inline">:temporary</code> </li> <li><code class="inline">:shutdown</code> - how to shut down the child </li> </ul> <p>Opposite to <a href="GenServer.html"><code class="inline">GenServer</code></a>, <a href="Agent.html"><code class="inline">Agent</code></a> and <a href="Supervisor.html"><code class="inline">Supervisor</code></a>, a Task has a default <code class="inline">:restart</code> of <code class="inline">:temporary</code>. This means the task will not be restarted even if it crashes. If you desire the task to be restarted for non-successful exits, do:</p> <pre><code class="nohighlight makeup elixir"><span class="kn">use</span><span class="w"> </span><span class="nc">Task</span><span class="p">,</span><span class="w"> </span><span class="ss">restart</span><span class="p">:</span><span class="w"> </span><span class="ss">:transient</span></code></pre> <p>If you want the task to always be restarted:</p> <pre><code class="nohighlight makeup elixir"><span class="kn">use</span><span class="w"> </span><span class="nc">Task</span><span class="p">,</span><span class="w"> </span><span class="ss">restart</span><span class="p">:</span><span class="w"> </span><span class="ss">:permanent</span></code></pre> <p>See the <a href="Supervisor.html"><code class="inline">Supervisor</code></a> docs for more information.</p> <h2 id="module-dynamically-supervised-tasks" class="section-heading"> <a href="#module-dynamically-supervised-tasks" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Dynamically supervised tasks </h2> <p>The <a href="Task.Supervisor.html"><code class="inline">Task.Supervisor</code></a> module allows developers to dynamically create multiple supervised tasks.</p> <p>A short example is:</p> <pre><code class="nohighlight makeup elixir"><span class="p" data-group-id="1260157766-1">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="n">pid</span><span class="p" data-group-id="1260157766-1">}</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Task.Supervisor</span><span class="o">.</span><span class="n">start_link</span><span class="p" data-group-id="1260157766-2">(</span><span class="p" data-group-id="1260157766-2">)</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Task.Supervisor</span><span class="o">.</span><span class="n">async</span><span class="p" data-group-id="1260157766-3">(</span><span class="n">pid</span><span class="p">,</span><span class="w"> </span><span class="k" data-group-id="1260157766-4">fn</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="c1"># Do something</span><span class="w"> </span><span class="k" data-group-id="1260157766-4">end</span><span class="p" data-group-id="1260157766-3">)</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">await</span><span class="p" data-group-id="1260157766-5">(</span><span class="n">task</span><span class="p" data-group-id="1260157766-5">)</span></code></pre> <p>However, in the majority of cases, you want to add the task supervisor to your supervision tree:</p> <pre><code class="nohighlight makeup elixir"><span class="nc">Supervisor</span><span class="o">.</span><span class="n">start_link</span><span class="p" data-group-id="7619931295-1">(</span><span class="p" data-group-id="7619931295-2">[</span><span class="w"> </span><span class="p" data-group-id="7619931295-3">{</span><span class="nc">Task.Supervisor</span><span class="p">,</span><span class="w"> </span><span class="ss">name</span><span class="p">:</span><span class="w"> </span><span class="nc">MyApp.TaskSupervisor</span><span class="p" data-group-id="7619931295-3">}</span><span class="w"> </span><span class="p" data-group-id="7619931295-2">]</span><span class="p" data-group-id="7619931295-1">)</span></code></pre> <p>Now you can dynamically start supervised tasks:</p> <pre><code class="nohighlight makeup elixir"><span class="nc">Task.Supervisor</span><span class="o">.</span><span class="n">start_child</span><span class="p" data-group-id="7186112092-1">(</span><span class="nc">MyApp.TaskSupervisor</span><span class="p">,</span><span class="w"> </span><span class="k" data-group-id="7186112092-2">fn</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="c1"># Do something</span><span class="w"> </span><span class="k" data-group-id="7186112092-2">end</span><span class="p" data-group-id="7186112092-1">)</span></code></pre> <p>Or even use the async/await pattern:</p> <pre><code class="nohighlight makeup elixir"><span class="nc">Task.Supervisor</span><span class="o">.</span><span class="n">async</span><span class="p" data-group-id="0641051961-1">(</span><span class="nc">MyApp.TaskSupervisor</span><span class="p">,</span><span class="w"> </span><span class="k" data-group-id="0641051961-2">fn</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="c1"># Do something</span><span class="w"> </span><span class="k" data-group-id="0641051961-2">end</span><span class="p" data-group-id="0641051961-1">)</span><span class="w"> </span><span class="o">|></span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">await</span><span class="p" data-group-id="0641051961-3">(</span><span class="p" data-group-id="0641051961-3">)</span></code></pre> <p>Finally, check <a href="Task.Supervisor.html"><code class="inline">Task.Supervisor</code></a> for other supported operations.</p> <h2 id="module-distributed-tasks" class="section-heading"> <a href="#module-distributed-tasks" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Distributed tasks </h2> <p>Since Elixir provides a Task supervisor, it is easy to use one to dynamically spawn tasks across nodes:</p> <pre><code class="nohighlight makeup elixir"><span class="c1"># On the remote node</span><span class="w"> </span><span class="nc">Task.Supervisor</span><span class="o">.</span><span class="n">start_link</span><span class="p" data-group-id="1626927702-1">(</span><span class="ss">name</span><span class="p">:</span><span class="w"> </span><span class="nc">MyApp.DistSupervisor</span><span class="p" data-group-id="1626927702-1">)</span><span class="w"> </span><span class="c1"># On the client</span><span class="w"> </span><span class="nc">Task.Supervisor</span><span class="o">.</span><span class="n">async</span><span class="p" data-group-id="1626927702-2">(</span><span class="p" data-group-id="1626927702-3">{</span><span class="nc">MyApp.DistSupervisor</span><span class="p">,</span><span class="w"> </span><span class="ss">:remote@local</span><span class="p" data-group-id="1626927702-3">}</span><span class="p">,</span><span class="w"> </span><span class="nc">MyMod</span><span class="p">,</span><span class="w"> </span><span class="ss">:my_fun</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="1626927702-4">[</span><span class="n">arg1</span><span class="p">,</span><span class="w"> </span><span class="n">arg2</span><span class="p">,</span><span class="w"> </span><span class="n">arg3</span><span class="p" data-group-id="1626927702-4">]</span><span class="p" data-group-id="1626927702-2">)</span></code></pre> <p>Note that, when working with distributed tasks, one should use the <a href="Task.Supervisor.html#async/4"><code class="inline">Task.Supervisor.async/4</code></a> function that expects explicit module, function and arguments, instead of <a href="Task.Supervisor.html#async/2"><code class="inline">Task.Supervisor.async/2</code></a> that works with anonymous functions. That’s because anonymous functions expect the same module version to exist on all involved nodes. Check the <a href="Agent.html"><code class="inline">Agent</code></a> module documentation for more information on distributed processes as the limitations described there apply to the whole ecosystem.</p> </section> <section id="summary" class="details-list"> <h1 class="section-heading"> <a class="hover-link" href="#summary"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this section</span> </a> Summary </h1> <div class="summary-types summary"> <h2> <a href="#types">Types</a> </h2> <div class="summary-row"> <div class="summary-signature"> <a href="#t:t/0">t()</a> </div> </div> </div> <div class="summary-functions summary"> <h2> <a href="#functions">Functions</a> </h2> <div class="summary-row"> <div class="summary-signature"> <a href="#__struct__/0">%Task{}</a> </div> <div class="summary-synopsis"><p>The Task struct</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#async/1">async(fun)</a> </div> <div class="summary-synopsis"><p>Starts a task that must be awaited on</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#async/3">async(mod, fun, args)</a> </div> <div class="summary-synopsis"><p>Starts a task that must be awaited on</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#async_stream/3">async_stream(enumerable, fun, options \\ [])</a> </div> <div class="summary-synopsis"><p>Returns a stream that runs the given function <code class="inline">fun</code> concurrently on each item in <code class="inline">enumerable</code></p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#async_stream/5">async_stream(enumerable, module, function, args, options \\ [])</a> </div> <div class="summary-synopsis"><p>Returns a stream that runs the given <code class="inline">module</code>, <code class="inline">function</code>, and <code class="inline">args</code> concurrently on each item in <code class="inline">enumerable</code></p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#await/2">await(task, timeout \\ 5000)</a> </div> <div class="summary-synopsis"><p>Awaits a task reply and returns it</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#child_spec/1">child_spec(arg)</a> </div> <div class="summary-synopsis"><p>Returns a specification to start a task under a supervisor</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#shutdown/2">shutdown(task, shutdown \\ 5000)</a> </div> <div class="summary-synopsis"><p>Unlinks and shuts down the task, and then checks for a reply</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#start/1">start(fun)</a> </div> <div class="summary-synopsis"><p>Starts a task</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#start/3">start(mod, fun, args)</a> </div> <div class="summary-synopsis"><p>Starts a task</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#start_link/1">start_link(fun)</a> </div> <div class="summary-synopsis"><p>Starts a process linked to the current process</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#start_link/3">start_link(mod, fun, args)</a> </div> <div class="summary-synopsis"><p>Starts a task as part of a supervision tree</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#yield/2">yield(task, timeout \\ 5000)</a> </div> <div class="summary-synopsis"><p>Temporarily blocks the current process waiting for a task reply</p> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#yield_many/2">yield_many(tasks, timeout \\ 5000)</a> </div> <div class="summary-synopsis"><p>Yields to multiple tasks in the given time interval</p> </div> </div> </div> </section> <section id="types" class="details-list"> <h1 class="section-heading"> <a class="hover-link" href="#types"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this section</span> </a> Types </h1> <div class="types-list"> <div class="detail" id="t:t/0"> <div class="detail-header"> <a href="#t:t/0" class="detail-link" title="Link to this type"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this type</span> </a> <span class="signature">t()</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L186" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>t() :: %Task{owner: <a href="typespecs.html#built-in-types">term</a>(), pid: <a href="typespecs.html#built-in-types">term</a>(), ref: <a href="typespecs.html#built-in-types">term</a>()}</pre> </div> </div> <section class="docstring"> </section> </div> </div> </section> <section id="functions" class="details-list"> <h1 class="section-heading"> <a class="hover-link" href="#functions"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this section</span> </a> Functions </h1> <div class="detail" id="__struct__/0"> <div class="detail-header"> <a href="#__struct__/0" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">%Task{}</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L184" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <span class="note">(struct)</span> </div> <section class="docstring"> <p>The Task struct.</p> <p>It contains these fields:</p> <ul> <li><p><code class="inline">:pid</code> - the PID of the task process; <code class="inline">nil</code> if the task does not use a task process</p> </li> <li><p><code class="inline">:ref</code> - the task monitor reference</p> </li> <li><p><code class="inline">:owner</code> - the PID of the process that started the task</p> </li> </ul> </section> </div> <div class="detail" id="async/1"> <div class="detail-header"> <a href="#async/1" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">async(fun)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L280" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>async((() -> <a href="typespecs.html#basic-types">any</a>())) :: <a href="#t:t/0">t</a>()</pre> </div> </div> <section class="docstring"> <p>Starts a task that must be awaited on.</p> <p>This function spawns a process that is linked to and monitored by the caller process. A <a href="Task.html#content"><code class="inline">Task</code></a> struct is returned containing the relevant information.</p> <p>Read the <a href="Task.html#content"><code class="inline">Task</code></a> module documentation for more info on general usage of <a href="#async/1"><code class="inline">async/1</code></a> and <a href="#async/3"><code class="inline">async/3</code></a>.</p> <p>See also <a href="#async/3"><code class="inline">async/3</code></a>.</p> </section> </div> <div class="detail" id="async/3"> <div class="detail-header"> <a href="#async/3" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">async(mod, fun, args)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L348" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>async(<a href="typespecs.html#built-in-types">module</a>(), <a href="typespecs.html#basic-types">atom</a>(), [<a href="typespecs.html#built-in-types">term</a>()]) :: <a href="#t:t/0">t</a>()</pre> </div> </div> <section class="docstring"> <p>Starts a task that must be awaited on.</p> <p>A <a href="Task.html#content"><code class="inline">Task</code></a> struct is returned containing the relevant information. Developers must eventually call <a href="Task.html#await/2"><code class="inline">Task.await/2</code></a> or <a href="Task.html#yield/2"><code class="inline">Task.yield/2</code></a> followed by <a href="Task.html#shutdown/2"><code class="inline">Task.shutdown/2</code></a> on the returned task.</p> <p>Read the <a href="Task.html#content"><code class="inline">Task</code></a> module documentation for more info on general usage of <a href="#async/1"><code class="inline">async/1</code></a> and <a href="#async/3"><code class="inline">async/3</code></a>.</p> <h2 id="async/3-linking" class="section-heading"> <a href="#async/3-linking" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Linking </h2> <p>This function spawns a process that is linked to and monitored by the caller process. The linking part is important because it aborts the task if the parent process dies. It also guarantees the code before async/await has the same properties after you add the async call. For example, imagine you have this:</p> <pre><code class="nohighlight makeup elixir"><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">heavy_fun</span><span class="p" data-group-id="2271169454-1">(</span><span class="p" data-group-id="2271169454-1">)</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">some_fun</span><span class="p" data-group-id="2271169454-2">(</span><span class="p" data-group-id="2271169454-2">)</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span></code></pre> <p>Now you want to make the <code class="inline">heavy_fun()</code> async:</p> <pre><code class="nohighlight makeup elixir"><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">async</span><span class="p" data-group-id="2651534499-1">(</span><span class="o">&</span><span class="n">heavy_fun</span><span class="o">/</span><span class="mi">0</span><span class="p" data-group-id="2651534499-1">)</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">some_fun</span><span class="p" data-group-id="2651534499-2">(</span><span class="p" data-group-id="2651534499-2">)</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">await</span><span class="p" data-group-id="2651534499-3">(</span><span class="n">x</span><span class="p" data-group-id="2651534499-3">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span></code></pre> <p>As before, if <code class="inline">heavy_fun/0</code> fails, the whole computation will fail, including the parent process. If you don’t want the task to fail then you must change the <code class="inline">heavy_fun/0</code> code in the same way you would achieve it if you didn’t have the async call. For example, to either return <code class="inline">{:ok, val} | :error</code> results or, in more extreme cases, by using <code class="inline">try/rescue</code>. In other words, an asynchronous task should be thought of as an extension of a process rather than a mechanism to isolate it from all errors.</p> <p>If you don’t want to link the caller to the task, then you must use a supervised task with <a href="Task.Supervisor.html"><code class="inline">Task.Supervisor</code></a> and call <a href="Task.Supervisor.html#async_nolink/2"><code class="inline">Task.Supervisor.async_nolink/2</code></a>.</p> <p>In any case, avoid any of the following:</p> <ul> <li><p>Setting <code class="inline">:trap_exit</code> to <code class="inline">true</code> - trapping exits should be used only in special circumstances as it would make your process immune to not only exits from the task but from any other processes.</p> <p>Moreover, even when trapping exits, calling <code class="inline">await</code> will still exit if the task has terminated without sending its result back.</p> </li> <li><p>Unlinking the task process started with <code class="inline">async</code>/<code class="inline">await</code>. If you unlink the processes and the task does not belong to any supervisor, you may leave dangling tasks in case the parent dies.</p> </li> </ul> <h2 id="async/3-message-format" class="section-heading"> <a href="#async/3-message-format" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Message format </h2> <p>The reply sent by the task will be in the format <code class="inline">{ref, result}</code>, where <code class="inline">ref</code> is the monitor reference held by the task struct and <code class="inline">result</code> is the return value of the task function.</p> </section> </div> <div class="detail" id="async_stream/3"> <span id="async_stream/2"></span> <div class="detail-header"> <a href="#async_stream/3" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">async_stream(enumerable, fun, options \\ [])</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L440" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <span class="note">(since 1.4.0)</span> <div class="specs"> <pre>async_stream(<a href="Enumerable.html#t:t/0">Enumerable.t</a>(), (<a href="typespecs.html#built-in-types">term</a>() -> <a href="typespecs.html#built-in-types">term</a>()), <a href="typespecs.html#built-in-types">keyword</a>()) :: <a href="Enumerable.html#t:t/0">Enumerable.t</a>()</pre> </div> </div> <section class="docstring"> <p>Returns a stream that runs the given function <code class="inline">fun</code> concurrently on each item in <code class="inline">enumerable</code>.</p> <p>Each <code class="inline">enumerable</code> item is passed as argument to the given function <code class="inline">fun</code> and processed by its own task. The tasks will be linked to the current process, similarly to <a href="#async/1"><code class="inline">async/1</code></a>.</p> <h2 id="async_stream/3-example" class="section-heading"> <a href="#async_stream/3-example" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Example </h2> <p>Count the codepoints in each string asynchronously, then add the counts together using reduce.</p> <pre><code class="nohighlight makeup elixir"><span class="gp unselectable">iex> </span><span class="n">strings</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p" data-group-id="7670410331-1">[</span><span class="s">"long string"</span><span class="p">,</span><span class="w"> </span><span class="s">"longer string"</span><span class="p">,</span><span class="w"> </span><span class="s">"there are many of these"</span><span class="p" data-group-id="7670410331-1">]</span><span class="w"> </span><span class="gp unselectable">iex> </span><span class="n">stream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">async_stream</span><span class="p" data-group-id="7670410331-2">(</span><span class="n">strings</span><span class="p">,</span><span class="w"> </span><span class="k" data-group-id="7670410331-3">fn</span><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">text</span><span class="w"> </span><span class="o">|></span><span class="w"> </span><span class="nc">String</span><span class="o">.</span><span class="n">codepoints</span><span class="p" data-group-id="7670410331-4">(</span><span class="p" data-group-id="7670410331-4">)</span><span class="w"> </span><span class="o">|></span><span class="w"> </span><span class="nc">Enum</span><span class="o">.</span><span class="n">count</span><span class="p" data-group-id="7670410331-5">(</span><span class="p" data-group-id="7670410331-5">)</span><span class="w"> </span><span class="k" data-group-id="7670410331-3">end</span><span class="p" data-group-id="7670410331-2">)</span><span class="w"> </span><span class="gp unselectable">iex> </span><span class="nc">Enum</span><span class="o">.</span><span class="n">reduce</span><span class="p" data-group-id="7670410331-6">(</span><span class="n">stream</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="k" data-group-id="7670410331-7">fn</span><span class="w"> </span><span class="p" data-group-id="7670410331-8">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="n">num</span><span class="p" data-group-id="7670410331-8">}</span><span class="p">,</span><span class="w"> </span><span class="n">acc</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">num</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">acc</span><span class="w"> </span><span class="k" data-group-id="7670410331-7">end</span><span class="p" data-group-id="7670410331-6">)</span><span class="w"> </span><span class="mi">47</span></code></pre> <p>See <a href="#async_stream/5"><code class="inline">async_stream/5</code></a> for discussion, options, and more examples.</p> </section> </div> <div class="detail" id="async_stream/5"> <span id="async_stream/4"></span> <div class="detail-header"> <a href="#async_stream/5" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">async_stream(enumerable, module, function, args, options \\ [])</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L414" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <span class="note">(since 1.4.0)</span> <div class="specs"> <pre>async_stream(<a href="Enumerable.html#t:t/0">Enumerable.t</a>(), <a href="typespecs.html#built-in-types">module</a>(), <a href="typespecs.html#basic-types">atom</a>(), [<a href="typespecs.html#built-in-types">term</a>()], <a href="typespecs.html#built-in-types">keyword</a>()) :: <a href="Enumerable.html#t:t/0">Enumerable.t</a>()</pre> </div> </div> <section class="docstring"> <p>Returns a stream that runs the given <code class="inline">module</code>, <code class="inline">function</code>, and <code class="inline">args</code> concurrently on each item in <code class="inline">enumerable</code>.</p> <p>Each item will be prepended to the given <code class="inline">args</code> and processed by its own task. The tasks will be linked to an intermediate process that is then linked to the current process. This means a failure in a task terminates the current process and a failure in the current process terminates all tasks.</p> <p>When streamed, each task will emit <code class="inline">{:ok, value}</code> upon successful completion or <code class="inline">{:exit, reason}</code> if the caller is trapping exits. Results are emitted in the same order as the original <code class="inline">enumerable</code>.</p> <p>The level of concurrency can be controlled via the <code class="inline">:max_concurrency</code> option and defaults to <a href="System.html#schedulers_online/0"><code class="inline">System.schedulers_online/0</code></a>. A timeout can also be given as an option representing the maximum amount of time to wait without a task reply.</p> <p>Finally, consider using <a href="Task.Supervisor.html#async_stream/6"><code class="inline">Task.Supervisor.async_stream/6</code></a> to start tasks under a supervisor. If you find yourself trapping exits to handle exits inside the async stream, consider using <a href="Task.Supervisor.html#async_stream_nolink/6"><code class="inline">Task.Supervisor.async_stream_nolink/6</code></a> to start tasks that are not linked to the current process.</p> <h2 id="async_stream/5-options" class="section-heading"> <a href="#async_stream/5-options" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Options </h2> <ul> <li><code class="inline">:max_concurrency</code> - sets the maximum number of tasks to run at the same time. Defaults to <a href="System.html#schedulers_online/0"><code class="inline">System.schedulers_online/0</code></a>. </li> <li><code class="inline">:ordered</code> - whether the results should be returned in the same order as the input stream. This option is useful when you have large streams and don’t want to buffer results before they are delivered. Defaults to <code class="inline">true</code>. </li> <li><code class="inline">:timeout</code> - the maximum amount of time (in milliseconds) each task is allowed to execute for. Defaults to <code class="inline">5000</code>. </li> <li><p><code class="inline">:on_timeout</code> - what to do when a task times out. The possible values are:</p> <ul> <li><code class="inline">:exit</code> (default) - the process that spawned the tasks exits. </li> <li><code class="inline">:kill_task</code> - the task that timed out is killed. The value emitted for that task is <code class="inline">{:exit, :timeout}</code>. </li> </ul> </li> </ul> <h2 id="async_stream/5-example" class="section-heading"> <a href="#async_stream/5-example" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Example </h2> <p>Let’s build a stream and then enumerate it:</p> <pre><code class="nohighlight makeup elixir"><span class="n">stream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">async_stream</span><span class="p" data-group-id="4132439898-1">(</span><span class="n">collection</span><span class="p">,</span><span class="w"> </span><span class="nc">Mod</span><span class="p">,</span><span class="w"> </span><span class="ss">:expensive_fun</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="4132439898-2">[</span><span class="p" data-group-id="4132439898-2">]</span><span class="p" data-group-id="4132439898-1">)</span><span class="w"> </span><span class="nc">Enum</span><span class="o">.</span><span class="n">to_list</span><span class="p" data-group-id="4132439898-3">(</span><span class="n">stream</span><span class="p" data-group-id="4132439898-3">)</span></code></pre> <p>The concurrency can be increased or decreased using the <code class="inline">:max_concurrency</code> option. For example, if the tasks are IO heavy, the value can be increased:</p> <pre><code class="nohighlight makeup elixir"><span class="n">max_concurrency</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">System</span><span class="o">.</span><span class="n">schedulers_online</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="n">stream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">async_stream</span><span class="p" data-group-id="3096462291-1">(</span><span class="n">collection</span><span class="p">,</span><span class="w"> </span><span class="nc">Mod</span><span class="p">,</span><span class="w"> </span><span class="ss">:expensive_fun</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="3096462291-2">[</span><span class="p" data-group-id="3096462291-2">]</span><span class="p">,</span><span class="w"> </span><span class="ss">max_concurrency</span><span class="p">:</span><span class="w"> </span><span class="n">max_concurrency</span><span class="p" data-group-id="3096462291-1">)</span><span class="w"> </span><span class="nc">Enum</span><span class="o">.</span><span class="n">to_list</span><span class="p" data-group-id="3096462291-3">(</span><span class="n">stream</span><span class="p" data-group-id="3096462291-3">)</span></code></pre> </section> </div> <div class="detail" id="await/2"> <span id="await/1"></span> <div class="detail-header"> <a href="#await/2" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">await(task, timeout \\ 5000)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L504" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>await(<a href="#t:t/0">t</a>(), <a href="typespecs.html#built-in-types">timeout</a>()) :: <a href="typespecs.html#built-in-types">term</a>() | <a href="typespecs.html#built-in-types">no_return</a>()</pre> </div> </div> <section class="docstring"> <p>Awaits a task reply and returns it.</p> <p>In case the task process dies, the current process will exit with the same reason as the task.</p> <p>A timeout, in milliseconds, can be given with default value of <code class="inline">5000</code>. If the timeout is exceeded, then the current process will exit. If the task process is linked to the current process which is the case when a task is started with <code class="inline">async</code>, then the task process will also exit. If the task process is trapping exits or not linked to the current process, then it will continue to run.</p> <p>This function assumes the task’s monitor is still active or the monitor’s <code class="inline">:DOWN</code> message is in the message queue. If it has been demonitored, or the message already received, this function will wait for the duration of the timeout awaiting the message.</p> <p>This function can only be called once for any given task. If you want to be able to check multiple times if a long-running task has finished its computation, use <a href="#yield/2"><code class="inline">yield/2</code></a> instead.</p> <h2 id="await/2-compatibility-with-otp-behaviours" class="section-heading"> <a href="#await/2-compatibility-with-otp-behaviours" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Compatibility with OTP behaviours </h2> <p>It is not recommended to <code class="inline">await</code> a long-running task inside an OTP behaviour such as <a href="GenServer.html"><code class="inline">GenServer</code></a>. Instead, you should match on the message coming from a task inside your <a href="https://hexdocs.pm/elixir/GenServer.html#handle_info/2"><code class="inline">GenServer.handle_info/2</code></a> callback.</p> <h2 id="await/2-examples" class="section-heading"> <a href="#await/2-examples" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Examples </h2> <pre><code class="nohighlight makeup elixir"><span class="gp unselectable">iex> </span><span class="n">task</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">async</span><span class="p" data-group-id="6823981159-1">(</span><span class="k" data-group-id="6823981159-2">fn</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="k" data-group-id="6823981159-2">end</span><span class="p" data-group-id="6823981159-1">)</span><span class="w"> </span><span class="gp unselectable">iex> </span><span class="nc">Task</span><span class="o">.</span><span class="n">await</span><span class="p" data-group-id="6823981159-3">(</span><span class="n">task</span><span class="p" data-group-id="6823981159-3">)</span><span class="w"> </span><span class="mi">2</span></code></pre> </section> </div> <div class="detail" id="child_spec/1"> <div class="detail-header"> <a href="#child_spec/1" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">child_spec(arg)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L194" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <span class="note">(since 1.5.0)</span> </div> <section class="docstring"> <p>Returns a specification to start a task under a supervisor.</p> <p>See <a href="Supervisor.html"><code class="inline">Supervisor</code></a>.</p> </section> </div> <div class="detail" id="shutdown/2"> <span id="shutdown/1"></span> <div class="detail-header"> <a href="#shutdown/2" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">shutdown(task, shutdown \\ 5000)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L760" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>shutdown(<a href="#t:t/0">t</a>(), <a href="typespecs.html#built-in-types">timeout</a>() | :brutal_kill) :: {:ok, <a href="typespecs.html#built-in-types">term</a>()} | {:exit, <a href="typespecs.html#built-in-types">term</a>()} | nil</pre> </div> </div> <section class="docstring"> <p>Unlinks and shuts down the task, and then checks for a reply.</p> <p>Returns <code class="inline">{:ok, reply}</code> if the reply is received while shutting down the task, <code class="inline">{:exit, reason}</code> if the task died, otherwise <code class="inline">nil</code>.</p> <p>The second argument is either a timeout or <code class="inline">:brutal_kill</code>. In case of a <code class="inline">timeout</code>, a <code class="inline">:shutdown</code> exit signal is sent to the task process and if it does not exit within the timeout, it is killed. With <code class="inline">:brutal_kill</code> the task is killed straight away. In case the task terminates abnormally (possibly killed by another process), this function will exit with the same reason.</p> <p>It is not required to call this function when terminating the caller, unless exiting with reason <code class="inline">:normal</code> or if the task is trapping exits. If the caller is exiting with a reason other than <code class="inline">:normal</code> and the task is not trapping exits, the caller’s exit signal will stop the task. The caller can exit with reason <code class="inline">:shutdown</code> to shutdown all of its linked processes, including tasks, that are not trapping exits without generating any log messages.</p> <p>If a task’s monitor has already been demonitored or received and there is not a response waiting in the message queue this function will return <code class="inline">{:exit, :noproc}</code> as the result or exit reason can not be determined.</p> </section> </div> <div class="detail" id="start/1"> <div class="detail-header"> <a href="#start/1" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">start(fun)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L251" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>start((() -> <a href="typespecs.html#basic-types">any</a>())) :: {:ok, <a href="typespecs.html#basic-types">pid</a>()}</pre> </div> </div> <section class="docstring"> <p>Starts a task.</p> <p>This is only used when the task is used for side-effects (i.e. no interest in the returned result) and it should not be linked to the current process.</p> </section> </div> <div class="detail" id="start/3"> <div class="detail-header"> <a href="#start/3" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">start(mod, fun, args)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L263" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>start(<a href="typespecs.html#built-in-types">module</a>(), <a href="typespecs.html#basic-types">atom</a>(), [<a href="typespecs.html#built-in-types">term</a>()]) :: {:ok, <a href="typespecs.html#basic-types">pid</a>()}</pre> </div> </div> <section class="docstring"> <p>Starts a task.</p> <p>This is only used when the task is used for side-effects (i.e. no interest in the returned result) and it should not be linked to the current process.</p> </section> </div> <div class="detail" id="start_link/1"> <div class="detail-header"> <a href="#start_link/1" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">start_link(fun)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L231" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>start_link((() -> <a href="typespecs.html#basic-types">any</a>())) :: {:ok, <a href="typespecs.html#basic-types">pid</a>()}</pre> </div> </div> <section class="docstring"> <p>Starts a process linked to the current process.</p> <p>This is often used to start the process as part of a supervision tree.</p> </section> </div> <div class="detail" id="start_link/3"> <div class="detail-header"> <a href="#start_link/3" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">start_link(mod, fun, args)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L239" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>start_link(<a href="typespecs.html#built-in-types">module</a>(), <a href="typespecs.html#basic-types">atom</a>(), [<a href="typespecs.html#built-in-types">term</a>()]) :: {:ok, <a href="typespecs.html#basic-types">pid</a>()}</pre> </div> </div> <section class="docstring"> <p>Starts a task as part of a supervision tree.</p> </section> </div> <div class="detail" id="yield/2"> <span id="yield/1"></span> <div class="detail-header"> <a href="#yield/2" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">yield(task, timeout \\ 5000)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L591" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>yield(<a href="#t:t/0">t</a>(), <a href="typespecs.html#built-in-types">timeout</a>()) :: {:ok, <a href="typespecs.html#built-in-types">term</a>()} | {:exit, <a href="typespecs.html#built-in-types">term</a>()} | nil</pre> </div> </div> <section class="docstring"> <p>Temporarily blocks the current process waiting for a task reply.</p> <p>Returns <code class="inline">{:ok, reply}</code> if the reply is received, <code class="inline">nil</code> if no reply has arrived, or <code class="inline">{:exit, reason}</code> if the task has already exited. Keep in mind that normally a task failure also causes the process owning the task to exit. Therefore this function can return <code class="inline">{:exit, reason}</code> only if</p> <ul> <li>the task process exited with the reason <code class="inline">:normal</code> </li> <li>it isn’t linked to the caller </li> <li>the caller is trapping exits </li> </ul> <p>A timeout, in milliseconds, can be given with default value of <code class="inline">5000</code>. If the time runs out before a message from the task is received, this function will return <code class="inline">nil</code> and the monitor will remain active. Therefore <a href="#yield/2"><code class="inline">yield/2</code></a> can be called multiple times on the same task.</p> <p>This function assumes the task’s monitor is still active or the monitor’s <code class="inline">:DOWN</code> message is in the message queue. If it has been demonitored or the message already received, this function will wait for the duration of the timeout awaiting the message.</p> <p>If you intend to shut the task down if it has not responded within <code class="inline">timeout</code> milliseconds, you should chain this together with <a href="#shutdown/1"><code class="inline">shutdown/1</code></a>, like so:</p> <pre><code class="nohighlight makeup elixir"><span class="k">case</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">yield</span><span class="p" data-group-id="1805401107-1">(</span><span class="n">task</span><span class="p">,</span><span class="w"> </span><span class="n">timeout</span><span class="p" data-group-id="1805401107-1">)</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">shutdown</span><span class="p" data-group-id="1805401107-2">(</span><span class="n">task</span><span class="p" data-group-id="1805401107-2">)</span><span class="w"> </span><span class="k" data-group-id="1805401107-3">do</span><span class="w"> </span><span class="p" data-group-id="1805401107-4">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="n">result</span><span class="p" data-group-id="1805401107-4">}</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="no">nil</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Logger</span><span class="o">.</span><span class="n">warn</span><span class="w"> </span><span class="s">"Failed to get a result in </span><span class="si" data-group-id="1805401107-5">#{</span><span class="n">timeout</span><span class="si" data-group-id="1805401107-5">}</span><span class="s">ms"</span><span class="w"> </span><span class="no">nil</span><span class="w"> </span><span class="k" data-group-id="1805401107-3">end</span></code></pre> <p>That ensures that if the task completes after the <code class="inline">timeout</code> but before <a href="#shutdown/1"><code class="inline">shutdown/1</code></a> has been called, you will still get the result, since <a href="#shutdown/1"><code class="inline">shutdown/1</code></a> is designed to handle this case and return the result.</p> </section> </div> <div class="detail" id="yield_many/2"> <span id="yield_many/1"></span> <div class="detail-header"> <a href="#yield_many/2" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">yield_many(tasks, timeout \\ 5000)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/task.ex#L663" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>yield_many([<a href="#t:t/0">t</a>()], <a href="typespecs.html#built-in-types">timeout</a>()) :: [ {<a href="#t:t/0">t</a>(), {:ok, <a href="typespecs.html#built-in-types">term</a>()} | {:exit, <a href="typespecs.html#built-in-types">term</a>()} | nil} ]</pre> </div> </div> <section class="docstring"> <p>Yields to multiple tasks in the given time interval.</p> <p>This function receives a list of tasks and waits for their replies in the given time interval. It returns a list of tuples of two elements, with the task as the first element and the yielded result as the second.</p> <p>Similarly to <a href="#yield/2"><code class="inline">yield/2</code></a>, each task’s result will be</p> <ul> <li><code class="inline">{:ok, term}</code> if the task has successfully reported its result back in the given time interval </li> <li><code class="inline">{:exit, reason}</code> if the task has died </li> <li><code class="inline">nil</code> if the task keeps running past the timeout </li> </ul> <p>Check <a href="#yield/2"><code class="inline">yield/2</code></a> for more information.</p> <h2 id="yield_many/2-example" class="section-heading"> <a href="#yield_many/2-example" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Example </h2> <p><a href="Task.html#yield_many/2"><code class="inline">Task.yield_many/2</code></a> allows developers to spawn multiple tasks and retrieve the results received in a given timeframe. If we combine it with <a href="Task.html#shutdown/2"><code class="inline">Task.shutdown/2</code></a>, it allows us to gather those results and cancel the tasks that have not replied in time.</p> <p>Let’s see an example.</p> <pre><code class="nohighlight makeup elixir"><span class="n">tasks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="mi">1</span><span class="o">.</span><span class="o">.</span><span class="mi">10</span><span class="w"> </span><span class="k" data-group-id="7545860349-1">do</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">async</span><span class="p" data-group-id="7545860349-2">(</span><span class="k" data-group-id="7545860349-3">fn</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Process</span><span class="o">.</span><span class="n">sleep</span><span class="p" data-group-id="7545860349-4">(</span><span class="n">i</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">1000</span><span class="p" data-group-id="7545860349-4">)</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="k" data-group-id="7545860349-3">end</span><span class="p" data-group-id="7545860349-2">)</span><span class="w"> </span><span class="k" data-group-id="7545860349-1">end</span><span class="w"> </span><span class="n">tasks_with_results</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">yield_many</span><span class="p" data-group-id="7545860349-5">(</span><span class="n">tasks</span><span class="p">,</span><span class="w"> </span><span class="mi">5000</span><span class="p" data-group-id="7545860349-5">)</span><span class="w"> </span><span class="n">results</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Enum</span><span class="o">.</span><span class="n">map</span><span class="p" data-group-id="7545860349-6">(</span><span class="n">tasks_with_results</span><span class="p">,</span><span class="w"> </span><span class="k" data-group-id="7545860349-7">fn</span><span class="w"> </span><span class="p" data-group-id="7545860349-8">{</span><span class="n">task</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="p" data-group-id="7545860349-8">}</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="c1"># Shutdown the tasks that did not reply nor exit</span><span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nc">Task</span><span class="o">.</span><span class="n">shutdown</span><span class="p" data-group-id="7545860349-9">(</span><span class="n">task</span><span class="p">,</span><span class="w"> </span><span class="ss">:brutal_kill</span><span class="p" data-group-id="7545860349-9">)</span><span class="w"> </span><span class="k" data-group-id="7545860349-7">end</span><span class="p" data-group-id="7545860349-6">)</span><span class="w"> </span><span class="c1"># Here we are matching only on {:ok, value} and</span><span class="w"> </span><span class="c1"># ignoring {:exit, _} (crashed tasks) and `nil` (no replies)</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p" data-group-id="7545860349-10">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="n">value</span><span class="p" data-group-id="7545860349-10">}</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">results</span><span class="w"> </span><span class="k" data-group-id="7545860349-11">do</span><span class="w"> </span><span class="nc">IO</span><span class="o">.</span><span class="n">inspect</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="k" data-group-id="7545860349-11">end</span></code></pre> <p>In the example above, we create tasks that sleep from 1 up to 10 seconds and return the number of seconds they slept. If you execute the code all at once, you should see 1 up to 5 printed, as those were the tasks that have replied in the given time. All other tasks will have been shut down using the <a href="Task.html#shutdown/2"><code class="inline">Task.shutdown/2</code></a> call.</p> </section> </div> </section> <footer class="footer"> <p> <span class="line"> Built using <a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" target="_blank" rel="help noopener">ExDoc</a> (v0.19.1), </span> <span class="line"> designed by <a href="https://twitter.com/dignifiedquire" target="_blank" rel="noopener" title="@dignifiedquire">Friedel Ziegelmayer</a>. </span> </p> </footer> </div> </div> </section> </div> <script src="dist/app-a0c90688fa.js"></script> </body> </html>