当前位置: 首页 > 知识库问答 >
问题:

我可以(或应该)在Web API控制器中使用IAsyncE的而不是任务

井洲
2023-03-14

我目前有一个网络 API

  • 使用FromSqlRaw(…)获取一行数据。存储库中的ToListAsync()
  • 将此数据作为OK(data. ToArray())作为任务返回

现在我想知道我是否应该或可以使用IAsyncE的可作为返回类型。这个想法是在存储库和控制器中使用它。然而,在这个(现在的deremit)线程中,它声明不应该使用它。这里提出的解决方案类似于:

FromSqlRaw(...).AsNoTracking().AsAsyncEnumerable()

至于控制器,我希望用< code>ActionResult包装响应,以显式设置返回代码。然而,这目前似乎并不奏效。

我应该只为存储库应用解决方案并将结果用作控制器中的列表还是保持原样?

共有2个答案

祁杰
2023-03-14

英寸使用系统时,MVC的. net 6 IAsyncEnumerable处理被更改。Text.Json:

MVC 不再缓冲 IAsyncEnumerable 实例。相反,MVC 依赖于 System.Text.Json 为这些类型添加的支持。

这意味着控制器将立即开始发送输出,客户端可以在收到响应块时开始处理它。

下面是一个借助新的最小API的例子:

endpoint绑定:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// this endpoint return IAsyncEnumerable<TestData>
app.MapGet("/asyncEnumerable/{count}", (int count) => GetLotsOfDataAsyncEnumerable(count));

// and this one returns Task<IEnumerable<TestData>>
app.MapGet("/{count}", async (int count) => await GetLotsOfDataAsync(count));
app.Run();

控制器方法:

async Task<IEnumerable<TestData>> GetLotsOfDataAsync(int count)
{
    var list = new List<TestData>();
    for (int i = 0; i < count; i++)
    {
        await Task.Delay(10);
        list.Add(new TestData($"{i}"));
    }
    return list;
}

async IAsyncEnumerable<TestData> GetLotsOfDataAsyncEnumerable(int count)
{
    for (int i = 0; i < count; i++)
    {
        await Task.Delay(10);
        yield return new TestData($"{i}");
    }
}

class TestData
{
    public string Field { get; }

    public TestData(string field)
    {
        Field = field;
    }
}

count-path变量允许控制我们希望在一次调用中检索多少数据。

我已经在windows机器上使用curl命令对其进行了测试(以下是解释如何使用curl衡量性能的答案),100个条目的结果:

                       /100        /asyncEnumerable/100
     time_namelookup:  0.000045s   0.000034s
        time_connect:  0.000570s   0.000390s
     time_appconnect:  0.000000s   0.000000s
    time_pretransfer:  0.000648s   0.000435s
       time_redirect:  0.000000s   0.000000s
  time_starttransfer:  1.833341s   0.014880s
                       ---------------------
          time_total:  1.833411s  1.673477s

这里要看的重要内容是 time_starttransfer,来自 curl manpage

时间,以秒为单位,从开始到第一个字节即将被传输。这包括time_pretransfer以及服务器计算结果所需的时间。

正如您所看到的,/ asyncEnumerable endpoint立即开始响应,当然,这种endpoint的客户端必须知道这种行为才能很好地利用它。

鞠嘉志
2023-03-14

IAsyncEnumerable为基于拉取的异步数据检索提供了一个接口。换句话说,此API表示一个迭代器,在该迭代器中异步获取下一个项。

这意味着您将分几轮接收数据,每一轮都是异步的。

>

  • 以前的 IAsyncEnumerable 您可以使用 IEnumerable

    任务

    让我们将这些知识应用于WebAPI:

    • 从HTTP消费者的角度来看,任务之间没有区别

    这意味着,如果API作为操作结果类型公开,则API的使用者无法利用IAsyncEnumerable

  •  类似资料:
    • 假设我有两种情况: 1) WebApi控制器 2) MVC控制器 我一直在阅读什么时候应该使用,似乎我应该在所有未直接绑定到UI的异步调用上使用。不过,我不知道这意味着什么...我应该使用? 我正在寻找一些明确的指导方针,关于我应该何时使用它。 这个问题不同于为所有服务器端代码调用ConfigureAwait的最佳实践——我在寻找一个关于这个方法在WebApi和MVC环境中的用例的直接答案,而不是

    • 寻找Reactor调度程序的指导。 我想在后台运行某些IO任务,即向技术团队发送电子邮件。为了使其异步,我使用Mono。fromRunnable订阅了调度程序。 我可以选择使用 Schedulers.elastic() 或 Schedulers.newElastic()。我更喜欢后者,因为它允许我给它一个唯一的名称,这将有助于日志分析。 做一个静态变量可以吗? 在Mono上订阅它,而不是每次都要创

    • 问题内容: 我现在已经实现了一些Java应用程序,到目前为止仅实现了桌面应用程序。我更喜欢使用不可变对象在应用程序中传递数据,而不是使用带有变量(setter 和getter )的对象,也称为JavaBeans。 但是在Java世界中,使用JavaBeans似乎更为常见,而且我不明白为什么应该使用JavaBeans。就个人而言,如果代码仅处理不可变的对象而不是始终改变状态,则代码看起来会更好。 在

    • 问题内容: 弹簧控制器类可以使用路径变量吗? 我知道我们可以在控制器的方法中使用路径变量。我们可以以相同的方式将其用于整个课堂吗? 例如: 我们可以这样使用吗?如果是,我们如何读取变量?实际上,根据我要响应的版本,我需要这种方法。如果无法采用上述方法,您能否建议我一个解决该问题的设计? 问题答案: 是的你可以。如果要在其中访问它,只需在您的方法中将其声明为@PathVariable。

    • 在代码不等待任何东西的异步方法中,是否有人会将其标记为异步,等待任务,然后返回? 除了潜在的联合国必要性之外,这样做的负面影响是什么? 对于本例,请假设

    • 问题内容: 从log.go(执行日志包): 只是一个函数包装器,为什么我应该用它代替or ? 有实际原因吗? 问题答案: 两件事不同: 通过包日志进行打印对于并发goroutine是安全的(而普通的则不是) 日志可以自动添加计时信息。 因此,这是两件完全不同的事情。log用于记录和格式化。(好吧,log使用相同的动词和标志,但这很方便)。