异步函数返回异步元数据(包括结果)而不仅仅是结果

Jes*_*ica 6 c# json asynchronous async-await .net-core

我正在使用 .NET Core 3.1 编写 API。这个 API 有一个名为 的异步函数GetSomeProperty(),我在端点(称为Get)中使用它。

当收到来自该端点的响应时,results属性被“下移”一层,并包装在来自异步方法的元数据中,如下所示:

"results": [
    {
        "result": {//actual result here}
        "id": 1,
        "status": 5,
        "isCanceled": false,
        "isCompleted": true,
        "creationOptions": 0,
        "isFaulted": false
    },
    {
        "result": {//actual result here}
        "id": 2,
        "status": 5,
        "isCanceled": false,
        "isCompleted": true,
        "creationOptions": 0,
        "isFaulted": false
    }
]
Run Code Online (Sandbox Code Playgroud)

我不希望这些结果被包装在这个“异步”包装器中。

在保持方法异步的同时,如何返回任务结果,而不是包含任务结果的对象?

我没有使用的原因有两个.Result

  1. 使用.Result被认为是不好的做法,因为如果任务尚未完成,它可能会导致锁定。
  2. 我想不出把它放在哪里。据我所知,它似乎不适合任何地方。

这是代码(请记住,出于示例目的,这已被显着稀释和简化):

[HttpGet]
public async Task<object> Get(string someParameter)
{   
    //Do stuff

    var things = BuildACollectionOfItems();
    var results = things.Select(x => x.IrrelevantThing).OrderBy(x => x.SomethingIrrelevant).Select(async x =>
    {
        return new
        {
            x.Id,
            SomeProperty = await GetSomeProperty(x.Id)
        };
    }).ToArray();

    return new
    {
        Results = ((IEnumerable<object>) results),
        SomeIrrelevantThing = someIrrelevantThing
    };
}

private async Task<bool> GetSomeProperty(int id)
{
    var somethingFromAServer = (await _thingProvider.GetThing()).TheProperty;

    //Do stuff here

    var thing = _context.Stuff.FirstOrDefault(x => x.Thing == somethingFromAServer);

    //Do some more stuff

    return thing.Stuff;
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*lay 5

你的Select回报IEnumerable<Task>(因为它传递了一个async函数);您可以使用Task.WhenAll等待它们全部完成,然后打开结果:

[HttpGet]
public async Task<object> Get(string someParameter)
{   
    //Do stuff

    var things = BuildACollectionOfItems();
    var results = await Task.WhenAll(things
        .Select(x => x.IrrelevantThing)
        .OrderBy(x => x.SomethingIrrelevant)
        .Select(async x => new
        {
            x.Id,
            SomeProperty = await GetSomeProperty(x.Id)
        }));

    return new
    {
        Results = ((IEnumerable<object>) results),
        SomeIrrelevantThing = someIrrelevantThing
    };
}
Run Code Online (Sandbox Code Playgroud)