C# 如何添加异步;等待“;添加到addrange select语句?

C# 如何添加异步;等待“;添加到addrange select语句?,c#,.net,select,task-parallel-library,async-await,C#,.net,Select,Task Parallel Library,Async Await,我有这样一个函数: public async Task<SomeViewModel> SampleFunction() { var data = service.GetData(); var myList = new List<SomeViewModel>(); myList.AddRange(data.select(x => new SomeViewModel { Id = x.Id, DateCr

我有这样一个函数:

public async Task<SomeViewModel> SampleFunction()
{
    var data = service.GetData();
    var myList = new List<SomeViewModel>();

    myList.AddRange(data.select(x => new SomeViewModel
    {
        Id = x.Id,
        DateCreated = x.DateCreated,
        Data = await service.GetSomeDataById(x.Id)
    }

    return myList;
}
public异步任务SampleFunction()
{
var data=service.GetData();
var myList=新列表();
myList.AddRange(data.select(x=>newsomeviewmodel
{
Id=x.Id,
DateCreated=x.DateCreated,
Data=wait service.GetSomeDataById(x.Id)
}
返回myList;
}

我的
await
无法工作,因为它只能用于标记有
async
修饰符的方法或lambda。使用此函数时,我应该将
async
放在哪里?

只能在
async
方法/委托中使用
await
。在这种情况下,必须将lambda表达式标记为
async

但是等等,还有更多

Select
来自前
async
时代,因此它不处理
async
lambdas(在您的情况下,它将返回
IEnumerable
而不是实际需要的
IEnumerable

但是你可以自己添加这个功能(最好是一个扩展方法),但是你需要考虑你是否希望<代码>等待/<代码>每个项目在移动到下一个(序列化)或<代码>等待< /COD>所有项目在一起结束(同时)。 顺序

async
用法
public Task SampleFunction()
{
return service.GetData().SelectAsync(async x=>new SomeViewModel
{
Id=x.Id,
DateCreated=x.DateCreated,
Data=wait service.GetSomeDataById(x.Id)
}
}

尽管对于您的用例来说可能过于繁重,但使用TPL数据流将使您能够更好地控制异步处理

public async Task<List<SomeViewModel>> SampleFunction()
{
    var data = service.GetData();

    var transformBlock = new TransformBlock<X, SomeViewModel>(
        async x => new SomeViewModel
        {
            Id = x.Id,
            DateCreated = x.DateCreated,
            Data = await service.GetSomeDataById(x.Id)
        },
        new ExecutionDataflowBlockOptions
        {
            // Let 8 "service.GetSomeDataById" calls run at once.
            MaxDegreeOfParallelism = 8
        });

    var result = new List<SomeViewModel>();

    var actionBlock = new ActionBlock<SomeViewModel>(
        vm => result.Add(vm));

    transformBlock.LinkTo(actionBlock,
        new DataflowLinkOptions { PropagateCompletion = true });

    foreach (var x in data)
    {
        transformBlock.Post(x);
    }
    transformBlock.Complete();

    await actionBlock.Completion;

    return result;
}
public异步任务SampleFunction()
{
var data=service.GetData();
var transformBlock=新transformBlock(
async x=>新的SomeViewModel
{
Id=x.Id,
DateCreated=x.DateCreated,
Data=wait service.GetSomeDataById(x.Id)
},
新的ExecutionDataflowBlockOptions
{
//让8个“service.GetSomeDataById”调用立即运行。
MaxDegreeOfParallelism=8
});
var result=新列表();
var actionBlock=新actionBlock(
vm=>result.Add(vm));
transformBlock.LinkTo(actionBlock,
新的DataflowLinkOptions{PropagateCompletion=true});
foreach(数据中的变量x)
{
柱(x);
}
transformBlock.Complete();
等待动作块完成;
返回结果;
}

如果
service.GetData()是
返回了一个
IObservable
,此方法返回了一个
IObservable
您在lambda内部使用的
await
,并且lambda将被编译器转换为它自己单独的命名方法。要使用
await
,它本身必须是
异步的,而不仅仅是在中定义的ode>async
方法。当您使lambda
async
时,您现在有一个任务序列,您希望将其异步转换为结果序列。
Task。Whalll
正是这样做的,因此我们可以将新查询传递到
Whalll
,以获得表示结果的任务,这正是我们遇到的霍德想回来:

public Task<SomeViewModel[]> SampleFunction()
{
    return Task.WhenAll(service.GetData().Select(
        async x => new SomeViewModel
    {
        Id = x.Id,
        DateCreated = x.DateCreated,
        Data = await service.GetSomeDataById(x.Id)
    }));
}
public Task SampleFunction()
{
return Task.WhenAll(service.GetData().Select(
async x=>新的SomeViewModel
{
Id=x.Id,
DateCreated=x.DateCreated,
Data=wait service.GetSomeDataById(x.Id)
}));
}

不太可能直接执行此操作,因为
Enumerable.Select()
不是异步方法。service.GetSomeDataByID的定义可能类似于
公共对象GetSomeDataByID(int Id)
如果未使用async关键字定义它,则不能使用wait调用它。它需要定义为
公共异步对象GetSomeDataByID(int Id)
它定义为“公共异步任务GetSomeDataByID(int Id)”'这在其他任何地方都适用。只是不在此添加范围内选择statement@Nick你不能等待
一个
对象
。它必须是
任务
。然而,塞尔曼22已经给出了正确的答案。@Nick因为提问者从技术上正确的答案中获得了更多的知识,而不是含糊不清的答案一个。您在这里使用的TPL数据流只是获取一个任务序列,并创建一个表示结果序列的任务。您可以通过一个方法调用来完成这一切,
task.whalll
,如我的回答所示。@Servy它所做的事情略多于此。“更精细的控制”在
TransformBlock
上的
ExecutionDataflowBlockOptions
规范中。例如,如果您正在访问web服务(通过
服务.GetSomeDataById
)可以处理8个并发请求的速度与处理1个请求的速度一样快,运行速度将快8倍。您的实现是正确的异步,但它仍然连续执行对
service.GetSomeDataById
的调用。@Servy我的上一段还提到,如果将
IObservable
用于“异步计算集合”而不是
IEnumerable
List
:)如果我要这样做,我可能会重构方法以进行那样的操作。我的答案中的代码不是串行的,而是并行执行查询。@Servy哦,你说得对。不过它没有速率限制,这在本例中可能不是问题。
public Task<SomeViewModel[]> SampleFunction()
{
    return service.GetData().SelectAsync(async x => new SomeViewModel
    {
        Id = x.Id,
        DateCreated = x.DateCreated,
        Data = await service.GetSomeDataById(x.Id)
    }
}
public async Task<List<SomeViewModel>> SampleFunction()
{
    var data = service.GetData();

    var transformBlock = new TransformBlock<X, SomeViewModel>(
        async x => new SomeViewModel
        {
            Id = x.Id,
            DateCreated = x.DateCreated,
            Data = await service.GetSomeDataById(x.Id)
        },
        new ExecutionDataflowBlockOptions
        {
            // Let 8 "service.GetSomeDataById" calls run at once.
            MaxDegreeOfParallelism = 8
        });

    var result = new List<SomeViewModel>();

    var actionBlock = new ActionBlock<SomeViewModel>(
        vm => result.Add(vm));

    transformBlock.LinkTo(actionBlock,
        new DataflowLinkOptions { PropagateCompletion = true });

    foreach (var x in data)
    {
        transformBlock.Post(x);
    }
    transformBlock.Complete();

    await actionBlock.Completion;

    return result;
}
public Task<SomeViewModel[]> SampleFunction()
{
    return Task.WhenAll(service.GetData().Select(
        async x => new SomeViewModel
    {
        Id = x.Id,
        DateCreated = x.DateCreated,
        Data = await service.GetSomeDataById(x.Id)
    }));
}