我正在使用.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
}
]
我不希望将这些结果包装在此“异步”包装器中。
在保持方法异步的同时,如何返回任务结果,而不是包含任务结果的对象?
我没有使用.Result
有两个原因:
.Result
被认为是不好的做法,因为如果任务尚未完成,则可能导致锁定。以下是代码(请记住,出于示例目的,此代码已被大大稀释和简化):
[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;
}
答案 0 :(得分: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
};
}