結局、並列化の本質は>>549なんだ。もう少し抽象化して書けば、こう。

foreach(var star1 , star2 in stars)
{
star1の新しく情報を書き込む領域 ← star1とstar2相互計算によって得る。
}
foreach(var star in stars)
{
starの新しく情報を書き込んだ領域をcommitする。
}

で、これをタスクシステム側に並列化する部分を受け持ってもらう。
例えば>>546であれば、次のように書けば上のプログラム(>>549)と等価になる構文を用意する。

foreach_parallel (var star1 , star2 in stars)
{
  star1.m_vx = star1.m_vx*star1.m_m/(star1.m_m+Star2.m_m) + Star2.m_vx*Star2.m_m/(star1.m_m+Star2.m_m);
  star1.m_vy = star1.m_vy*star1.m_m/(star1.m_m+Star2.m_m) + Star2.m_vy*Star2.m_m/(star1.m_m+Star2.m_m);
}

このとき、左辺は、shadow(m_vx_new , m_vy_new ) に対してアクセスしていて、実際はforeachを抜けてから

foreach(var star in stars)
{
  star.m_vx = star1.m_vx_new;
  star.m_vy = star1.m_vx_new;
}

これが実行される。この仕組みをタスクシステム側に提供してもらう。これなら簡単に並列化できる。
ゲームで使うコリジョン判定などはたいていこのように並列化できる。