47

Microsoft は本日 (2010 年 10 月 28 日)、非同期メソッド実行のために C#/VB にandキーワードを導入するVisual Studio Async CTPを発表しました。asyncawait

最初は、コンパイラがキーワードをスレッドの作成に変換すると思っていましたが、ホワイト ペーパーと Anders Hejlsberg のPDC プレゼンテーション(31:00) によると、非同期操作は完全にメイン スレッドで行われます。

同じスレッドで操作を並行して実行するにはどうすればよいですか? 技術的にどのように可能であり、IL で実際に翻訳された機能は何ですか?

4

3 に答える 3

84

yield returnC# 2.0のキーワードと同様に機能します。

非同期メソッドは、実際には通常の順次メソッドではありません。これは、いくつかの状態を持つステート マシン (オブジェクト) にコンパイルされます (ローカル変数はオブジェクトのフィールドに変換されます)。を 2 回使用する間の各コード ブロックはawait、ステート マシンの 1 つの「ステップ」です。

これは、メソッドが開始されると、最初のステップを実行するだけで、ステート マシンが戻り、実行する作業をスケジュールすることを意味します。作業が完了すると、ステート マシンの次のステップが実行されます。たとえば、このコード:

async Task Demo() { 
  var v1 = foo();
  var v2 = await bar();
  more(v1, v2);
}

次のようなものに翻訳されます。

class _Demo {
  int _v1, _v2;
  int _state = 0; 
  Task<int> _await1;
  public void Step() {
    switch(this._state) {
    case 0: 
      this._v1 = foo();
      this._await1 = bar();
      // When the async operation completes, it will call this method
      this._state = 1;
      op.SetContinuation(Step);
    case 1:
      this._v2 = this._await1.Result; // Get the result of the operation
      more(this._v1, this._v2);
  }
}

重要な部分は、メソッドを使用しSetContinuationて、操作が完了したときにStepメソッドを再度呼び出す必要があることを指定することです (メソッドは、フィールドを使用して元のコードの 2 番目のビットを実行する必要があることを認識してい_stateます)。SetContinuationは のようなものbtn.Click += Stepで、単一のスレッドで完全に実行されることは容易に想像できます。

C# の非同期プログラミング モデルは、F# の非同期ワークフローに非常に似ており (実際、いくつかの技術的な詳細を除けば、本質的に同じものです)、リアクティブなシングル スレッド GUI アプリケーションを使用して記述することasyncは、非常に興味深い領域です。少なくとも私はそう思います。たとえば、この記事を参照してください(おそらく、今すぐ C# バージョンを作成する必要があります :-))。

変換は反復子 (および) に似てyield returnおり、実際、以前は反復子を使用して C# で非同期プログラミングを実装することができました。しばらく前にそれについての記事を書きましたが、翻訳がどのように機能するかについての洞察を得ることができると思います.

于 2010-10-28T22:19:37.223 に答える
49

同じスレッドで操作を並行して実行するにはどうすればよいですか?

できません。非同期性は「並列処理」または「同時実行」ではありません。非同期は並列処理で実装される場合もあれば、実装されない場合もあります。作業を小さなチャンクに分割し、作業の各チャンクをキューに入れ、スレッドが他に何もしていないときはいつでも作業の各チャンクを実行することで実装できます。

私のブログには、これらすべてがどのように機能するかについての一連の記事があります。この質問に直接関係するものは、おそらく来週の木曜日に上がるでしょう。時計

リンク

詳細については。

于 2010-10-29T23:49:40.757 に答える
8

私が理解しているように、asyncandキーワードは、メソッドがキーワードを使用するawaitたびに、コンパイラーがメソッドの残りの部分を、非同期操作が完了したときにスケジュールされた継続に変換します。これにより、メソッドはすぐに呼び出し元に戻り、非同期部分が完了したときに作業を再開できます。asyncawaitasync

入手可能な論文によると、それには多くの詳細がありますが、私が間違っていない限り、それがその要点です。

私が見ているように、非同期メソッドの目的は、多くのコードを並行して実行することではなく、非同期メソッドを必要に応じて呼び出すことができるいくつかの小さなチャンクに分割することです。重要な点は、コンパイラがタスク/継続を使用してコールバックのすべての複雑な配線を処理することです。これにより、複雑さが軽減されるだけでなく、非同期メソッドを従来の同期コードのように多かれ少なかれ記述できるようになります。

于 2010-10-28T21:53:38.343 に答える