1

MVC4 / NET 4.5 非同期アクション メソッドを考えてみましょう。このメソッドには、IO にバインドされた順序どおりの操作が 2 つあり、どちらも IAsyncResult パターンに従います。以下に、System.DirectoryServices.Protocols 名前空間を使用して簡単な例を作成しました。私は長い間 .NET の TPL やその他の非同期モデル (および node.js のようなコールバックを多用するモデル) のファンでしたが、ようやく async/await に取り掛かりました。

「await」で示されているように、適切な結果が返されますが、.ContinueWith と Task.Factory.FromAsync で同じ結果を得る方法に困惑しました。後者は、処理の混乱のコードを便利に軽減しますIAsyncResult またはコールバックの構文の混乱。

私のサンプル コードは、既に最適な方法で処理を行っているのではないでしょうか? .ContinueWith は、より慣用的なアプローチのように思えますが (そうですか?)、新しい Task を継続としてチェーンする方法が見つかりませんでした。Func の継続は、委譲せずにここでそれをカットするつもりはありません。

public async Task<ActionResult> AjaxStuff()
    {
        var c = new LdapConnection(string.Empty);

        var t1 = Task.Factory.FromAsync<string>(
            c.BeginSendRequest(new SearchRequest(string.Empty, "(&(objectClass=*))", SearchScope.Base, "defaultNamingContext"), PartialResultProcessing.NoPartialResultSupport, null, null),
            iar =>
            {
                return ((SearchResponse)c.EndSendRequest(iar)).Entries[0].Attributes["defaultNamingContext"][0].ToString();
            });

        var nc = await t1;

        var t2 = Task.Factory.FromAsync<string>(
            c.BeginSendRequest(new SearchRequest(nc, "(&(givenName=steve))", SearchScope.Subtree), PartialResultProcessing.NoPartialResultSupport, null, null),
            iar =>
            {
                var result = (SearchResponse)c.EndSendRequest(iar);
                return result.Entries.Count > 0 ? result.Entries[0].DistinguishedName : "no such thing";
            });

        return this.PartialView("AjaxStuff", await t2);
    }
4

1 に答える 1

8

await確かに よりもきれいなコードになりContinueWithます。

FromAsyncとはいえ、コールバックを指定しない方が使いやすいです。FromAsyncまた、単純な拡張メソッドでラップすることも好みます。

public static Task<DirectoryResponse> SendRequestAsync(this LdapConnection c, DirectoryRequest request, PrtialResultProcessing partialMode)
{
    return Task.Factory<DirectoryResponse>.FromAsync(c.BeginSendRequest, c.EndSendRequest, request, partialMode, null);
}

次に、次のように使用できます。

public async Task<ActionResult> AjaxStuff()
{
    var c = new LdapConnection(string.Empty);

    var result1 = await c.SendRequestAsync(new SearchRequest(string.Empty, "(&(objectClass=*))", SearchScope.Base, "defaultNamingContext"), PartialResultProcessing.NoPartialResultSupport);
    var nc = ((SearchResponse)result1).Entries[0].Attributes["defaultNamingContext"][0].ToString();

    var result2 = (SearchResponse)(await c.SendRequestAsync(new SearchRequest(nc, "(&(givenName=steve))", SearchScope.Subtree), PartialResultProcessing.NoPartialResultSupport)));
    var dn = result2.Entries.Count > 0 ? result2.Entries[0].DistinguishedName : "no such thing";

    return this.PartialView("AjaxStuff", dn);
}

コードをシンプルに保つことFromAsyncで、すべてのロジックを 1 つのメソッドに移動し、awaitはるかに読みやすくなります。

于 2013-09-20T16:41:26.770 に答える