如何解决这个foreach的最干净的异步版本?
我在 AWS Lambda 中有一个方法可以接收完整的项目列表。它处理这些项目,然后将它们插入到 Dynamo 数据库表中。处理或插入数据库的顺序无关紧要。
我正在寻找最线程安全但易于理解的方式来加快运行速度;通过使用 async await
或其他(可能是并行的?)操作。
我在想 Parallel.ForEach()
但这似乎有点沉重。有没有更简单、更明显的方法?
private async Task<int> LoadAutocomplete(IList<Item> resp)
{
var client = new AmazonDynamoDBClient();
foreach (var item in resp)
{
var request = new PutItemRequest
{
TableName = EnvironmentHelper.DynamoTableName,Item = new Dictionary<string,AttributeValue>()
{
{ "LANGUAGE",new AttributeValue { S = item.LANGUAGE }},{ "COUNTRY",new AttributeValue { S = item.COUNTRY }}
}
};
await client.PutItemAsync(request);
System.Threading.Thread.Sleep(100);
}
}
选项 1
private async Task<int> LoadAutocomplete(IList<Item> resp)
{
var client = new AmazonDynamoDBClient();
Parallel.ForEach(resp,async item =>
{
var request = new PutItemRequest
{
TableName = EnvironmentHelper.DynamoTableName,new AttributeValue { S = item.COUNTRY }}
}
};
await client.PutItemAsync(request);
}
}
选项 2 会导致编译器抱怨 LoadAutoComplete 方法“缺少 await 运算符并且将同步运行”。
选项 2 正如@jamesfaix 所建议的
private async Task<int> LoadAutocomplete(IList<Item> resp)
{
var client = new AmazonDynamoDBClient();
var tasks = items.Select(x => DoSomethingAsync(client,x)).ToList();
await Task.WhenAll(tasks);
}
private DoSomething(AmazonDynamoDBClient client,Item item)
{
var request = new PutItemRequest
{
TableName = EnvironmentHelper.DynamoTableName,AttributeValue>()
{
{ "LANGUAGE",new AttributeValue { S = item.COUNTRY }}
}
};
await client.PutItemAsync(request);
}
选项 + @martin 建议
帖子 "Use Parallel.For in batches in dotnet core" 确实回答了我的问题,但我选择了 @jamesfaix 发布的 the answer,因为它大大改进了我的代码。
解决方法
以下是我首先要做的一些基本更改。您可能还可以从那里进行其他改进。
- 避免在异步代码中使用
Thread.Sleep
。Task.Delay
是异步等效项。 - 在等待任何任务之前创建许多任务。如果可以,运行时将尝试同时运行一些。
private async Task<int> LoadAutocomplete2(IList<Item> resp)
{
var client = new AmazonDynamoDBClient();
var tasks = resp.Select(async item =>
{
var request = new PutItemRequest
{
TableName = EnvironmentHelper.DynamoTableName,Item = new Dictionary<string,AttributeValue>()
{
{ "LANGUAGE",new AttributeValue { S = item.LANGUAGE }},{ "COUNTRY",new AttributeValue { S = item.COUNTRY }}
}
};
var result = await client.PutItemAsync(request);
await Task.Delay(100);
return result;
})
.ToList(); // Make sure to materialize the IEnumerable!
await Task.WhenAll(tasks);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。