私はStackOverflowを初めて使用しますが、Microsoftで作業しているチームに所属しているので、非同期CTPについて質問されていることに驚いています:)
私はあなたが何を目指しているのか理解していると思います、そしてあなたがそこに到達するためにあなたが正しくやっていることがいくつかあります。
私があなたが望むと思うもの:
static async Task Test()
{
// Do something, await something
}
static void Main(string[] args)
{
// In the CTP, use Task.RunEx(...) to run an Async Method or Async Lambda
// on the .NET thread pool
var t = TaskEx.RunEx(Test);
// the above was just shorthand for
var t = TaskEx.RunEx(new Func<Task>(Test));
// because the C# auto-wraps methods into delegates for you.
// Doing much more in this same thread
t.Wait(); // Waiting for much more then just this single task, this is just an example
}
Task.RunとTask.RunEx
このCTPは.NET4.0の上にインストールされるため、mscorlibの実際のタイプにパッチを適用する必要はありませんでした。 System.Threading.Tasks.Task
代わりに、プレイグラウンドAPIは、競合する場合はFooExという名前になります。
なぜそれらRun(...)
のいくつかといくつかに名前を付けたのRunEx(...)
ですか?その理由は、CTPをリリースするまでにまだ完了していなかったメソッドのオーバーロードの再設計によるものです。現在動作しているコードベースでは、C#メソッドのオーバーロードルールを微調整して、非同期ラムダに対して正しいことが行われるようにする必要がありました。これにより、、、、またはが返される可能性がvoid
ありTask
ますTask<T>
。
問題は、非同期メソッドまたはラムダがTask
またはTask<T>
を返す場合、タスクはメソッドまたはラムダの呼び出しの一部として自動的に生成されるため、実際にはreturn式に外部タスクタイプがないことです。通常、returnステートメントの式はメソッドまたはラムダのreturn型に直接変換できるため、これはコードを明確にするための適切なエクスペリエンスを強く望んでいますが、以前はまったく異なっていました。
したがって、非同期void
ラムダと非同期Task
ラムダの両方が引数なしでサポートreturn;
されます。したがって、どちらを選択するかを決定するために、メソッドのオーバーロード解決を明確にする必要があります。したがって、Run(...)とRunEx(...)の両方を使用する唯一の理由は、PDC 2010がヒットするまでに、非同期CTPの他の部分をより高品質でサポートできるようにするためです。
非同期メソッド/ラムダについて考える方法
これが混乱のポイントであるかどうかはわかりませんが、私はそれについて言及したいと思いました-非同期メソッドまたは非同期ラムダを書いているとき、それはそれを呼び出す人の特定の特性を帯びることがあります。これは、次の2つのことを前提としています。
- あなたが待っているタイプ
- そしておそらく同期コンテキスト(上記に応じて)
待機用のCTP設計と現在の内部設計はどちらも非常にパターンベースであるため、APIプロバイダーは、「待機」できる活気に満ちた一連の機能を具体化するのに役立ちます。これは、待機しているタイプによって異なる可能性があり、その一般的なタイプはですTask
。
Task
の待機の実装は非常に合理的であり、現在のスレッドに依存してSynchronizationContext
作業を延期する方法を決定します。すでにWinFormsまたはWPFメッセージループに入っている場合、延期された実行は同じメッセージループに戻ります(BeginInvoke()
「メソッドの残りの部分」を使用したかのように)。タスクを待っていて、すでに.NETスレッドプールを使用している場合、「メソッドの残りの部分」はスレッドプールスレッドの1つで再開されます(ただし、必ずしも同じスレッドである必要はありません)。ほとんどの場合、最初に利用可能なプールスレッドを使用して満足しています。
Wait()メソッドの使用に関する注意
使用したサンプルでは、次のようになります。
var t = TaskEx.Run( () => Test().Wait() );
それは何ですか:
- 周囲のスレッドで、TaskEx.Run(...)を同期的に呼び出して、スレッドプールでラムダを実行します。
- ラムダにはスレッドプールスレッドが指定されており、非同期メソッドを呼び出します。
- 非同期メソッドTest()はラムダから呼び出されます。ラムダはスレッドプールで実行されていたため、Test()内の継続は、スレッドプール内の任意のスレッドで実行できます。
- ラムダは、待機がなかったため、実際にはそのスレッドのスタックを空にしません。この場合のTPLの動作は、Wait()呼び出しの前にTest()が実際に終了したかどうかによって異なります。ただし、この場合、Test()が別のスレッドで実行を終了するのを待機している間、スレッドプールスレッドをブロックする可能性があります。
これが「await」演算子の主な利点です。元のスレッドをブロックすることなく、後で実行するコードを追加できることです。スレッドプールの場合、スレッドの使用率を向上させることができます。
VBまたはC#の非同期CTPについて他に質問がある場合は、お知らせください。ぜひお聞かせください:)