title: What is the correct way to switch freely between asynchronous tasks?
body: <p>Suppose I have some tasks running asynchronously. They may be totally independent, but I still want to set points where the tasks will pause so they can run concurrently.</p>
  <p>What is the correct way to run the tasks concurrently? I am currently using <code>await asyncio.sleep(0)</code>, but I feel this is adding a lot of overhead.</p>
  <pre><code>import asyncio
  
  async def do(name, amount):
      for i in range(amount):
          # Do some time-expensive work
          print(f'{name}: has done {i}')
  
          await asyncio.sleep(0)
  
      return f'{name}: done'
  
  async def main():
      res = await asyncio.gather(do('Task1', 3), do('Task2', 2))
      print(*res, sep='\n')
  
  loop = asyncio.get_event_loop()
  
  loop.run_until_complete(main())
  </code></pre>
  <h2>Output</h2>
  <pre><code>Task1: has done 0
  Task2: has done 0
  Task1: has done 1
  Task2: has done 1
  Task1: has done 2
  Task1: done
  Task2: done
  </code></pre>
  <p>If we were using simple generators, an empty <code>yield</code> would pause the flow of a task without any overhead, but empty <code>await</code> are not valid.</p>
  <p>What is the correct way to set such breakpoints without overhead?</p>