我有一个场景,我必须为列表中的每个项目调用相同的数据库存储过程。我不想使用foreach,因为它会降低性能,这将是最好的选择parllel foeach或async / await foreach?
以下是示例代码
public Task<List<object>> CallMethod()
{
foreach(var obj in input)
{
List.Add(await Task.Run(() =>CallDatabase(obj)));
}
return List;
}
public CallDatabase(object)
{
//Code to call DB
}
从DB收到的所有对象都是独立的。
经过一番研究后,我打算使用异步调用,这会改善性能吗?
答案 0 :(得分:2)
我不确定这会有什么不同。我假设您仍然需要等待加载所有结果,在这种情况下async
没有帮助,您的瓶颈很可能是网络I / O和服务器处理而不是本地CPU,所以并行也无济于事。
也就是说,如果您不需要查询结果而不关心是否存在错误,那么async
可能有助于实现“即发即弃”。
您最大的收获可能是尝试在一个查询中获得多个结果,而不是触发一堆个别查询。
答案 1 :(得分:1)
Defintiely Async
,Parallel.ForEach
用于计算密集型操作。它遍布可用的核心资源并相应地协调它们。相反,Async仅用于此类操作:向服务发出请求,继续并在资源请求之前接收通知。
答案 2 :(得分:1)
这主要是对D Stanley's answer的评论 - 切换到并行/异步代码不太可能提高性能。
如果您的主要关注点是响应性/可伸缩性 - 异步会更好,因为通常数据库访问是IO绑定操作。它还允许在顺序和并行处理之间进行选择(即,如果您的数据库层由于某种原因不支持同一连接上的并发请求)。此外,使用async
时,如果使用默认同步上下文,则更容易获得更新UI /请求的同步。
顺序:它将运行与非异步解决方案一样长,但线程可以同时执行其他活动(对于WinForms / WPF等UI应用程序)或进程请求(ASP.Net)。 / p>
async public Task<ResultType> CallMethodAsync()
{
foreach(var obj in input)
{
var singleResult = await CallDatabaseAsync(obj);
// combine results if needed
}
// return combined results
}
并行:将同时运行所有请求,可能比顺序解决方案更快。
async public Task<ResultType> CallMethodAsync()
{
List<Task<SingleResultType>> tasks = new List<Task<SingleResultType>>();
foreach(var obj in input)
{
tasks.Add(await CallDatabaseAsync(obj));
}
await Task.WhenAll(tasks);
foreach(SingleResultType result in tasks.Select(t=>t.Result))
{
// combine results if needed
}
// return combined results
}
请注意async
通常要求所有代码都是异步的 - 所以如果只转换一小段代码并行运行Parallel.ForEach
可能更容易解决,因为它不涉及处理{{ 3}}
答案 3 :(得分:0)
我已经实施了一个解决方案;不确定这种异步或者是否会提高性能,我对异步非常新,所以不要太在意。
public static async Task<List<Response>> Execute(Request objInput)
{
List<Response> objList = new List<Response>();
foreach (object obj in objInput.objs)
{
objList.Add(await Task.Run(() =>GetDataFromDB(obj)));
}
return objList;
}
private static object GetDataFromDB(object obj)
{
//Call DB and build the object
}
如果这不是实现异步的正确方法,那么请提供其他想法。