( グルの場合:yield'ahのコルーチン内 )
理論のビット
Asyncメソッドは、待機ごとに終了するコルーチンであり、待機が完了するとこの時点から復元されます(作成者は、実行が常にawaitによって中断されるわけではなく、タスクインスタンスだけでなく「期待」できることを知っています)。 したがって、サブネットの2番目のバージョンから開始すると、yieldキーワードを使用してコルーチンを簡単に作成できます。 このツールを使用します。
コンセプト
C#5.0のように記述したいのですが、同時に言語拡張機能をインストールしないでください。 残念ながら、これは機能しません。 しかし、そのようなオプションがあります:
private IEnumerable Login(...) { // ... // get user id, if not specified if (string.IsNullOrEmpty(uid)) { var getUserIdTask = lient.GetUserId(...); yield return getUserIdTask; // await uid= getUserIdTask.Result.uid; } // login var loginTask = lient.Login(...); yield return loginTask; // await var sessionId = loginTask.Result.SessionId; // getting user's profile var getUserInfoTask = lient.GetUserInfo(...); yield return getUserInfoTask; // await var userInfo = getUserInfoTask.Result; // ... yield return userInfo; // return }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
      yield returnを介して返され、Taskの継承者ではないものはすべて、非同期メソッドの実行の結果と見なされます。
実装
コードはこちらです。
操作のメカニズムは簡単です:
- ルートタスクを作成して呼び出し元に返す
 - イテレーターを回転させる
 - タスクが戻った場合、ContinueWithを介してステップ2に移行して完了するまで待ちます
 - エラーが返された場合、馬タスクの例外をスローします
 - 値が返された場合、指定された結果でタスクTaskを完了します
 - イテレータが終了したら、タスクTaskを標準結果で完了します
 
完了のすべてのバリアントでは、反復子でDisposeが呼び出されます。これにより、使用中のリソースが解放され、try / finallyブロックが使用されます。
FromIteratorメソッドを呼び出すことにより、新しい非同期タスクを開始できます。
 private IEnumerable Login(...) { ... } Task loginTask = TaskUtils.FromIterator(this.Login(...)); //     Task<UserInfo> loginTask = TaskUtils.FromIterator<UserInfo>(this.Login(...));
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     
      オプションで、次を指定できます。
- state- Task.AsyncStateに分類される状態
 - creationFlags-ルートタスクのTaskCreationOptions 。 TaskCreationOptions.LongRunningを設定すると、現在のスレッドをブロックしたくないため、すべての作業を別のスレッドで行う必要があります。
 - cancelToken-非同期メソッドの実行を中断するためのトークン。可能な限り深く渡されます
 
おわりに
長所:
- コンパクトで清潔
 - 管理されていないリソースを恐れることはできません。
 - パッチを追加する必要はありません。 図書館
 - モノで動作します
 
短所:
- Asyncメソッドは、TaskではなくIEnumerableを返します。 タスクを返す追加のメソッドを作成する必要がある場合があります。
 - タスクのインスタンスのみを待つことができます
 - 「期待される」タスクのエラーは、try / catchを介して処理できません(ContinueWithを介して可能)。 予想されるタスクでエラーが発生すると、ルートタスクで例外がスローされ、実行スレッドは非同期メソッドを訪問しなくなります。
 - 内部実装クラス(TaskBuilder)は、予想されるタスクでContinueWithをサブスクライブする場合を除き、それ自体への参照を生成せず、GCを構築することができます。
 
マイナスのほとんどは、何らかの方法で克服することができます。
テキストのエラーはPMに送信できます。
ソースコード 。