Chaining Task.Factory.FromAsync and ContinueWith vs. await

本文关键字:ContinueWith vs await and FromAsync Task Factory Chaining | 更新日期: 2023-09-27 18:32:13

考虑一个MVC4/NET 4.5异步操作方法,该方法有两个IO绑定的顺序操作要执行,这两个操作都遵循IAsyncResult模式。 下面我创建了一个使用 System.DirectoryServices.Protocols 命名空间的简单示例。 虽然我一直是 .NET 中的 TPL 和其他异步模型(以及像 node.js 这样的回调密集型模型)的粉丝,但我终于开始使用 async/await。

如"await"所示,它返回正确的结果,但我对获得相同结果的方法感到困惑。ContinueWith 和 Task.Factory.FromAsync,后者有效地减轻了处理 IAsyncResult 的代码混乱或回调的语法混乱。

也许我的示例代码已经以最佳方式做事了?.继续似乎是更惯用的方法(或者它是吗?),但我找不到任何方法将新任务链接为延续;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);
    }

Chaining Task.Factory.FromAsync and ContinueWith vs. await

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代码简单,您可以将所有逻辑移动到单个方法中,await使其更具可读性。