···327327When you pass the same `AsyncIterable` or `StreamTask` argument to multiple tasks, each task gets its own copy of the data. Use `channel()` to share a single source across multiple workers — each item goes to exactly one consumer (work stealing).
328328329329```ts
330330-import { workers, channel, mo } from 'moroutine';
330330+import { workers, channel, assign, mo } from 'moroutine';
331331332332const generate = mo(import.meta, async function* (n: number) {
333333 for (let i = 0; i < n; i++) yield i;
···344344const ch = channel(generate(100));
345345346346{
347347- using run = workers(4);
348348- const [a, b, c, d] = await run([process(ch), process(ch), process(ch), process(ch)]);
347347+ using run = workers();
348348+ const fanout = run.workers.map((w) => {
349349+ return assign(w, process(ch));
350350+ });
351351+ const results = await run(fanout);
349352 // Items distributed across workers — no duplicates, no gaps
350353}
351354```
355355+356356+Use `assign(worker, task)` to pin a task to a specific worker. `run.workers` is a read-only array of worker handles, one per pool worker.
352357353358Without `channel()`, `AsyncIterable` and `StreamTask` arguments are auto-detected and streamed to a single consumer. `channel()` is only needed for fan-out.
354359