c# - 匿名异步,怎样才是正确的做法?

标签 c# asynchronous async-await

我有一个做同步事情的简单类,

public static class Synchronous
{
    public static void DoTheWholeThing()
    {
        AStuff aStuff;
        using (var a = new A())
        {
            aStuff = a.GetStuff();
        }

        BStuff bStuff;
        using (var b = new B())
        {
            bStuff = b.GetStuff();
        }

        var combination = CombineStuff(aStuff, bStuff);
    }

    private static Combination CombineStuff(AStuff aStuff, BStuff bStuff)
    {
        //// Magic Here
    }
}

显然,这段代码没有完全定义,但它确实说明了我的问题。

现在,类 AB两者都负责从不同的远程源检索数据。因此,A 的开发者和 B已经实现了称为 GetStuffAsync 的异步入口点返回 Task<AStuff>Task<BStuff>分别。

我想最大限度地利用异步方法并同时调用它们,这样我就可以减少代码的总体等待时间。

到目前为止,这是我编造的内容。

public static class Asynchronous
{
    public async static Task DoTheWholeThing(CancellationToken cancellationToken)
    {
        var getAStuffTask  = new Func<Task<AStuff>>(
                async () =>
                    {
                        using (var a = new A())
                        {
                            return await a.GetStuffAsync(cancellationToken);
                        }
                    })();

        var getBStuffTask  = new Func<Task<BStuff>>(
                async () =>
                    {
                        using (var b = new B())
                        {
                            return await b.GetStuffAsync(cancellationToken);
                        }
                    })();

        var combination = CombineStuff(
            await getAStuffTask,
            await getBStuffTask);
    }

    private Combination CombineStuff(AStuff aStuff, BStuff bStuff)
    {
        //// Magic Here
    }
}

除了这段代码看起来很像 javascript 模块模式之外,这是正确的方法吗?我认为我不应该使用 Task.Run 因为此代码是 clearly not CPU bound .

似乎有点“笨拙”,我需要实例化类型化委托(delegate)来执行此操作。有没有更好的办法?

编辑

继两个很好的答案之后,我在命名函数和延续之间进退两难。

最佳答案

当您简单地将匿名方法提取到命名方法中时,代码会变得非常简单:

public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
    var getAStuffTask = GetAStuffAsync(cancellationToken);
    var getBStuffTask = GetBStuffAsync(cancellationToken);

    var combination = CombineStuff(
        await getAStuffTask,
        await getBStuffTask);
}

private static async Task<AStuff> GetAStuffAsync(CancellationToken cancellationToken)
{
    using (var a = new A())
    {
        return await a.GetStuffAsync(cancellationToken);
    }
}
private static async Task<BStuff> GetBStuffAsync(CancellationToken cancellationToken)
{
    using (var b = new B())
    {
        return await b.GetStuffAsync(cancellationToken);
    }
}

就是说,如果您真的想坚持使用匿名方法,您可以创建一个辅助方法,它允许泛型类型推断和 lambda 隐式确定委托(delegate)的类型:

public async static Task DoTheWholeThing(CancellationToken cancellationToken)
{
    var getAStuffTask = Start(async () =>
            {
                using (var a = new A())
                {
                    return await a.GetStuffAsync(cancellationToken);
                }
            });

    var getBStuffTask = Start(async () =>
            {
                using (var b = new B())
                {
                    return await b.GetStuffAsync(cancellationToken);
                }
            });

    var combination = CombineStuff(
        await getAStuffTask,
        await getBStuffTask);
}
public static Task<T> Start<T>(Func<Task<T>> asyncOperation)
{
    return asyncOperation();
}

关于c# - 匿名异步,怎样才是正确的做法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32378681/

相关文章:

node.js - 环回异步/等待 UnhandledPromiseRejectionWarning 问题

c# - MSTest 测试上下文异常处理

c# - 动态创建 Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>?

c# - PID Controller 积分项导致极度不稳定

android - 在异步 Http 客户端上设置超时

c# - 异步 I/O 密集型代码比非异步代码运行速度慢,为什么?

c# - 如何拥有自动递增的版本号(Visual Studio)?

node.js - 在 NodeJs 中使用 async await 和 mariadb 查询的正确方法是什么?

javascript - Firebase 中的递归错误太多

javascript - 是否可以在没有 return 关键字的情况下解析异步函数