【问题标题】:Implementing async version of a sync method: How to return Task<int> which is constant 1?实现同步方法的异步版本:如何返回常量 1 的 Task<int>?
【发布时间】:2015-05-21 07:01:18
【问题描述】:

我有一个同步方法,现在我想实现它的异步版本。幸运的是,底层调用已经有一个异步版本 (dbSet.SaveChangesAsync()),但是在我的算法中,有一个 if 分支返回常量字面量 1。

不知道这部分在异步版本中如何实现?

同步版本:

    public virtual int Add(T entity)
    {
        SetLogContext(entity, _logctx);
        dbSet.Add(entity);

        if (isAutonomous)
        {
            return ctx.SaveChanges();
        }
        return 1;
    }

异步版本:

    public virtual Task<int> AddAsync(T entity)
    {
        SetLogContext(entity, _logctx);
        dbSet.Add(entity);

        if (isAutonomous)
        {
            return ctx.SaveChangesAsync();
        }
        return ??? // What to write here?
    }

【问题讨论】:

  • return Task.FromResult(1);
  • Doomer:这似乎是一个答案,你为什么不把它写成答案?

标签: c# .net async-await


【解决方案1】:

使用

return Task.FromResult(1);

【讨论】:

  • 可以找到文档here
【解决方案2】:

你有两种可能如何实现你的需求:一种是使用async关键字:

public virtual async Task<int> AddAsync<T>(T entity)
{
    SetLogContext(entity, _logctx);
    dbSet.Add(entity);

    if (isAutonomous)
    {
        return await ctx.SaveChangesAsync();
    }
    return 1;
}

另一种是在要返回号码的地方使用Task.FromResult(1)

【讨论】:

  • 当我读到第一个(async/await)在这种情况下有点反模式......它创建了一个额外的不必要的状态机。
【解决方案3】:

我在这里看到的问题是您创建了一个实际上不是async 的“异步”方法。这可能会误导下一个使用它的人。

正如@xxMUROxx 已经提到的,“异步”方法应该以async 关键字为前缀。

    public virtual async Task<int> AddAsync<T>(T entity)
    {
        SetLogContext(entity, _logctx);
        dbSet.Add(entity);

        if (isAutonomous)
        {
            return await ctx.SaveChangesAsync();
        }
        return 1;
    }

使用async await 模式的全部意义在于change the way the program flows through methods。当await 关键字被命中时,该方法返回给调用者并且通常一直流回到原来的调用者。通常这将是一个async void 事件处理程序,例如按钮单击。

发生这种情况时,它允许调用线程在等待长时间运行的操作完成时继续执行。长时间运行的操作完成后,代码将创建一个延续并继续执行任何其他依赖于返回结果的代码。

通过在方法中省略async 关键字,您有效地使调用再次同步。一开始就违背了调用SaveChangesAsync的目的。

【讨论】:

  • 调用代码肯定可以await一个方法返回的任务,不管该方法是否使用async/await本身?
  • 文档中都有详细说明。 > "await 关键字只能在标有async 的方法中使用" msdn.microsoft.com/en-AU/library/hh156528.aspx
  • 但这与您的答案中的主要主张完全不同,即不能调用返回 Task 但不使用 async/await 的方法异步。
  • 没错,无论async 关键字如何,您都可以异步运行从该方法返回的任务,因为它委托给另一个async 方法。我想我只是陷入了方法命名的语义中。我很抱歉。
  • @craftworkgames 我意识到这是旧的,但命名约定建议开发人员将Async 附加到任何返回Task 的方法上,而不是依赖于该方法实际上执行一些操作的想法内部async 任务。我个人觉得命名约定很愚蠢。它闻起来有匈牙利符号的味道,我们选择在内部省略它。我等不及微软放弃它了。
猜你喜欢
  • 1970-01-01
  • 2015-03-27
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
  • 2022-06-21
  • 1970-01-01
相关资源
最近更新 更多