理想的には適切なスレッド制限を使用して、コレクション内のすべてのMyObjectで同時に(戻りオブジェクトをキャプチャしながら)すべてのDoWork()タスクを非同期で実行するための正しい/最もパフォーマンスの高い方法は何でしょうか。
これを行う最も簡単な方法は、Task.WhenAll次の方法です。
ReturnObject[] results = await Task.WhenAll(collection.Select(x => x.DoWork()));
これにより、コレクション内のDoWorkすべてが呼び出され、MyObjectsすべてが完了するのを待ちます。スレッドプールは、すべてのスロットルを適切に処理します。
  すべてのアイテムが完了するのを待つのではなく、すべての個々のDoWork()リターンをすぐにキャプチャしたい場合、別の方法はありますか?
はい、 JonSkeetとStephenToubによって説明された方法を使用できます。AsyncExライブラリ(NuGetから入手可能)にも同様のソリューションがあり、次のように使用できます。
// "tasks" is of type "Task<ReturnObject>[]"
var tasks = collection.Select(x => x.DoWork()).OrderByCompletion();
foreach (var task in tasks)
{
  var result = await task;
  ...
}