调用Parallel.Foreach中的方法并将结果保存到线程安全列表中

Call method in Parallel.Foreach and save the result into the thread safe list

我有这段代码 运行 在单线程中没问题

foreach (var meetingRoom in meetingRooms)
{
            try
            {
                var res = calendarService.GetEvents(meetingRoom.Email, startUtc, endUtc, lightweight, limit);
                result.AddRange(res);
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }
}

但问题是 meetingRooms 列表包含超过 40 000 个条目。我正在尝试接近 Parallel.Foreach - 这是我目前所得到的:

Parallel.ForEach(meetingRooms, () => 0,(meetingRoom) =>
        {
            var res = calendarService.GetEvents(meetingRoom.Email, startUtc, endUtc, lightweight, limit);

        }
        ,
        finalResult =>
        {
            lock (result)
            {
                result.Add(finalResult);
            }
        });

我不太了解第四个参数 localFinally 的工作原理。

请注意,result 和 meetingRooms 是具有不同数据类型的列表。

编辑:

我已经实施了 PLINQ 解决方案,如其中一个答案所示。看起来它的工作,但 Exchange Web 服务 (EWS) 库没有实现并行调用它的方法之一。获取和 Microsoft 代码抛出的错误 "Not a unique key!"。

您可以使用 PLinq。

result = meetingRooms
  .AsParallel()
  .Select(meetingRoom => calendarService.GetEvents(meetingRoom.Email, startUtc, endUtc, lightweight, limit) )
  .ToList();

当您仍想使用 Parallel.ForEach() 时,使用 localFinally 的重载就没那么有用了。使用基础知识:

Parallel.ForEach(meetingRooms, meetingRoom =>
    {
        var res = calendarService.GetEvents(meetingRoom.Email, ...);

        lock (result) // only OK when you don't lock on it anywhere else
        {
            result.Add(res);
        }
    });

您也可以使用 ConcurrentBag (or ConcurrentQueue or ConcurrentDictionary) 来存储结果并避免锁定。