Parllel Foreach与Async Foreach进行数据库通话

时间:2015-10-05 14:23:21

标签: c# asynchronous foreach

我有一个场景,我必须为列表中的每个项目调用相同的数据库存储过程。我不想使用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收到的所有对象都是独立的。

经过一番研究后,我打算使用异步调用,这会改善性能吗?

4 个答案:

答案 0 :(得分:2)

我不确定这会有什么不同。我假设您仍然需要等待加载所有结果,在这种情况下async没有帮助,您的瓶颈很可能是网络I / O和服务器处理而不是本地CPU,所以并行也无济于事。

也就是说,如果您不需要查询结果而不关心是否存在错误,那么async可能有助于实现“即发即弃”。

您最大的收获可能是尝试在一个查询中获得多个结果,而不是触发一堆个别查询。

答案 1 :(得分:1)

Defintiely AsyncParallel.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
  }

如果这不是实现异步的正确方法,那么请提供其他想法。

相关问题