C# 异步填充字典
我有一个简单的C# 异步填充字典,c#,.net,asp.net-core,.net-core,C#,.net,Asp.net Core,.net Core,我有一个简单的foreach循环(如下所示),它迭代一个集合,并根据当前迭代器值进行异步API调用以获取数据 foreach(组中的变量组) { var usersInGroup=wait this.tableauService.GetUsersInTableauGroup(group.Id); //请使用“usersInGroup”` } 我不希望每次迭代都进行API调用,而是希望为每个API调用创建一个异步任务,并同时执行它们,结果填充由group.Id键入的字典。这可能吗 在我看来,代码
foreach
循环(如下所示),它迭代一个集合,并根据当前迭代器值进行异步API调用以获取数据
foreach(组中的变量组)
{
var usersInGroup=wait this.tableauService.GetUsersInTableauGroup(group.Id);
//请使用“usersInGroup”`
}
我不希望每次迭代都进行API调用,而是希望为每个API调用创建一个异步任务,并同时执行它们,结果填充由group.Id
键入的字典。这可能吗
在我看来,代码应该是这样的:
IList tasks=new List();
IDictionary dictionary=新字典();
foreach(组中的var组)
{
添加(this.tableauService.getUsersInTableAugGroup(group.Id));
//以某种方式定义每个任务的回调以创建字典
}
等待任务。何时(任务);
您希望为并行化,而不是每个循环周期内的工作。使用Parallel.ForEach
您想要并行化的,而不是每个循环周期内的工作。使用Parallel.ForEach
尝试以下代码:
public async Task<(string name, int id)> Aggregate(int id)
{
var result = await this.tableauService.GetUsersInTableauGroup(id);
return (result, id);
}
...
var tasks = await Task.WhenAll(groups.Select(g => Aggregate(g.Id)));
var dict = tasks.ToDictionary(k => k.id, k => k.name);
公共异步任务聚合(int-id)
{
var result=wait this.tableauService.getUsersInTableAugGroup(id);
返回(结果、id);
}
...
var tasks=wait Task.WhenAll(groups.Select(g=>Aggregate(g.Id));
var dict=tasks.ToDictionary(k=>k.id,k=>k.name);
它将异步运行所有API调用,一旦所有这些请求完成,我们就可以根据结果安全地创建一个字典,请尝试以下代码:
public async Task<(string name, int id)> Aggregate(int id)
{
var result = await this.tableauService.GetUsersInTableauGroup(id);
return (result, id);
}
...
var tasks = await Task.WhenAll(groups.Select(g => Aggregate(g.Id)));
var dict = tasks.ToDictionary(k => k.id, k => k.name);
公共异步任务聚合(int-id)
{
var result=wait this.tableauService.getUsersInTableAugGroup(id);
返回(结果、id);
}
...
var tasks=wait Task.WhenAll(groups.Select(g=>Aggregate(g.Id));
var dict=tasks.ToDictionary(k=>k.id,k=>k.name);
它将异步运行所有API调用,一旦所有这些请求完成,我们就可以安全地从任务的结果创建一个字典。WhenAll()返回任务的所有值,因此您可以执行以下操作:
var tasks = groups
.Select(async g => new
{
g.Id,
Values = await this.tableauService.GetUsersInTableauGroup(g.Id)
});
var results = await Task.WhenAll(tasks);
var dictionary = results
.ToDictionary(r => r.Id, r => r.Values);
Task.WhenAll()返回任务的所有值,因此可以执行以下操作:
var tasks = groups
.Select(async g => new
{
g.Id,
Values = await this.tableauService.GetUsersInTableauGroup(g.Id)
});
var results = await Task.WhenAll(tasks);
var dictionary = results
.ToDictionary(r => r.Id, r => r.Values);
只有键操作不是线程安全的,读取键是线程安全的,他没有在代码中显示如何使用字典。一本普通的字典
可能很好。OP特别指出他正在尝试填充字典,这意味着他将调用Add
。。。。或者使用:ConcurrentDictionary
只有键操作不是线程安全的,读取键是线程安全的,他没有在代码中显示他如何使用字典。一本普通的字典
可能很好。OP特别指出他正在尝试填充字典,这意味着他将调用Add
。。。。或者使用:concurrentdirectionary
@SoheilAlizadeh:No,它生成一个任务
——返回Func
。(否则,Task.whalll()
如何等待这些任务并得到它们的结果?@SoheilAlizadeh它不会返回空,它是一个Func
@StriplingWarrior似乎是一个很好的解决方案,我没法四处走动,可能需要咖啡……谢谢。让我知道是否有任何部分我可以帮助更好地解释。这正是我想要的,谢谢@StriplingWarrior@SoheilAlizadeh:否,这将生成一个任务
——返回Func
。(否则,Task.whalll()
如何等待这些任务并得到它们的结果?@SoheilAlizadeh它不会返回空,它是一个Func
@StriplingWarrior似乎是一个很好的解决方案,我没法四处走动,可能需要咖啡……谢谢。如果有什么地方我可以更好地解释,请告诉我。这正是我想要的,谢谢@StriplingWarrior