C# 此foreach的最干净异步版本?
我在AWS Lambda中有一个方法,它接收完整的项目列表。它处理这些项,然后将它们插入到Dynamo DB表中。处理或插入数据库的顺序无关紧要 我正在寻找最安全的线程,但易于理解的方式,使它运行得更快;通过使用C# 此foreach的最干净异步版本?,c#,.net-core,foreach,async-await,C#,.net Core,Foreach,Async Await,我在AWS Lambda中有一个方法,它接收完整的项目列表。它处理这些项,然后将它们插入到Dynamo DB表中。处理或插入数据库的顺序无关紧要 我正在寻找最安全的线程,但易于理解的方式,使它运行得更快;通过使用异步等待或其他(可能是并行的?)操作 我在想Parallel.ForEach(),但这似乎有点沉重。有没有更简单、更明显的方法 private async Task<int> LoadAutocomplete(IList<Item> resp) { var
异步等待
或其他(可能是并行的?)操作
我在想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);
}
}
专用异步任务LoadAutocomplete(IList resp)
{
var client=new AmazonDynamoDBClient();
foreach(resp中的var项目)
{
var请求=新的PutItemRequest
{
TableName=EnvironmentHelper.DynamoTableName,
Item=新字典()
{
{“语言”,新属性值{S=item.LANGUAGE},
{“国家”,新属性值{S=item.COUNTRY}
}
};
等待client.PutItemAsync(请求);
系统线程线程睡眠(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,
Item = new Dictionary<string, AttributeValue>()
{
{ "LANGUAGE", new AttributeValue { S = item.LANGUAGE }},
{ "COUNTRY", new AttributeValue { S = item.COUNTRY }}
}
};
await client.PutItemAsync(request);
}
}
专用异步任务LoadAutocomplete(IList resp)
{
var client=new AmazonDynamoDBClient();
Parallel.ForEach(resp,异步项=>
{
var请求=新的PutItemRequest
{
TableName=EnvironmentHelper.DynamoTableName,
Item=新字典()
{
{“语言”,新属性值{S=item.LANGUAGE},
{“国家”,新属性值{S=item.COUNTRY}
}
};
等待client.PutItemAsync(请求);
}
}
选项2导致编译器抱怨LoadAutoComplete方法“缺少等待运算符,将同步运行”
选项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,
Item = new Dictionary<string, AttributeValue>()
{
{ "LANGUAGE", new AttributeValue { S = item.LANGUAGE }},
{ "COUNTRY", new AttributeValue { S = item.COUNTRY }}
}
};
await client.PutItemAsync(request);
}
专用异步任务LoadAutocomplete(IList resp)
{
var client=new AmazonDynamoDBClient();
var tasks=items.Select(x=>DoSomethingAsync(client,x)).ToList();
等待任务。何时(任务);
}
私人剂量测量(AmazondynamodClient客户端,项目)
{
var请求=新的PutItemRequest
{
TableName=EnvironmentHelper.DynamoTableName,
Item=新字典()
{
{“语言”,新属性值{S=item.LANGUAGE},
{“国家”,新属性值{S=item.COUNTRY}
}
};
等待client.PutItemAsync(请求);
}
选项+由@martin建议
这篇文章确实回答了我的问题,但我选择了@jamesfaix发布,因为它极大地改进了我的代码。这里是我开始时要做的一些基本更改。可能还有其他改进
Thread.Sleep
。Task.Delay
是异步等价物专用异步任务LoadAutocomplete2(IList resp)
{
var client=new AmazonDynamoDBClient();
var tasks=resp.Select(异步项=>
{
var请求=新的PutItemRequest
{
TableName=EnvironmentHelper.DynamoTableName,
Item=新字典()
{
{“语言”,新属性值{S=item.LANGUAGE},
{“国家”,新属性值{S=item.COUNTRY}
}
};
var result=await client.PutItemAsync(请求);
等待任务。延迟(100);
返回结果;
})
.ToList();//确保实现IEnumerable!
等待任务。何时(任务);
}
以下是我开始时要做的一些基本更改。您还可以从中进行其他改进
Thread.Sleep
。Task.Delay
是异步等价物专用异步任务LoadAutocomplete2(IList resp)
{
var client=new AmazonDynamoDBClient();
var tasks=resp.Select(异步项=>
{
var请求=新的PutItemRequest
{
TableName=EnvironmentHelper.DynamoTableName,
Item=新字典()
{
{“语言”,新属性值{S=item.LANGUAGE},
{“国家”,新属性值{S=item.COUNTRY}
}
};
var result=await client.PutItemAsync(请求);
等待任务。延迟(100);
返回结果;
})
.ToList();//确保实现IEnumerable!
等待任务。何时(任务);
}
不要在异步代码中使用Sleep
。使用等待任务。延迟
啊,是的。我实际上已经删除了那一行,但忘了在这里。我可能会被它难住,因为我似乎记得需要那一行来确保DB插入正确执行。在选项1和选项2之间,我更关心的是行为的不同比语法更简洁。您可以不费吹灰之力就拒绝“选项1”。Parallel.ForEach
。您在“DB插入正确执行”中提到过,通过在操作之间添加100毫秒的延迟。在异步代码中不要使用Sleep
。使用wait Task.delay
啊,是的。我实际上已经删除了该行,但忘了在这里。无论如何,我可能会被它难倒,因为我似乎记得需要该行来确保DB插入正确执行。在选项1和选项2之间,我将ld更关心的是行为差异而不是语法清洁度。您可以不费吹灰之力就拒绝“选项1”。Parallel.ForEach
。您在文章中提到的“DB插入正确执行”,在操作之间增加了100毫秒的延迟。谢谢@jamesfaix-这将执行时间从1:20缩短到了0:03:)为什么它对我很重要
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);
}