Приведу три примера выборки из коллекций с использованием PlINQ. 1 Пример
//List<MDRItem> startMdrItems, List<SDSItem> sdsItemsGlobal это коллекции кастомных классов
//передаются в метод в качестве параметров
var mdrFiltered = (from mdrItem in startMdrItems.AsParallel()
from sdsItem in sdsItemsGlobal.AsParallel()
where mdrItem.TitleNumber == sdsItem.TitleNumber && sdsItem.TitleStatus == "Активный"
select mdrItem
).ToList();
2 пример
//List<TSRItem> tsrFiltered, List<SDSItem> sdsItems это коллекции кастомных классов
var tsrFilteredSecond = (from tsrItem in tsrFiltered.AsParallel()
from sdsItem in sdsItems.AsParallel()
where tsrItem.TitleNumber == sdsItem.TitleNumber && sdsItem.TitleStatus == "Активный"
select new TSRItem()
{
RowIdx = tsrItem.RowIdx,
FileName = tsrItem.FileName,
ProjectFromSchedule = tsrItem.ProjectFromSchedule,
ProjectName = tsrItem.ProjectName,
GosFinSign = sdsItem.GosFinSign
}
);
3 пример
//List<TSRItem> tsrFilteredSecond коллекция кастомного класса
var listToForeach = new ConcurrentBag<TSRItem>(tsrFilteredSecond);
ConcurrentBag<TSRItem> filterdTsrItems = new ConcurrentBag<TSRItem>();
listToForeach.AsParallel().ForAll/*.ForEach*/(tsr =>
{
var chekedTitleNumber = String.IsNullOrEmpty(tsr.TitleNumber) ? "" : tsr.TitleNumber;
var chekedMark = String.IsNullOrEmpty(tsr.Mark) ? "" : string.Concat(":", tsr.Mark);
tsr.MarkSMGenerated = GenerateMarkSM(tsr.PurchaseSpecification);
var checkedMarkSm = String.IsNullOrEmpty(tsr.MarkSMGenerated) ? "" : string.Concat(":", tsr.MarkSMGenerated);
tsr.NomenclatureGroupMTOGenerated = GenerateGroupMTO(tsr);
var checkedNomenclatureGroupMTOGenerated = String.IsNullOrEmpty(tsr.NomenclatureGroupMTOGenerated) ? "" : string.Concat(":", tsr.NomenclatureGroupMTOGenerated);
tsr.BuildingcodeGenerated = GenerateBulidingCode(tsr);
var checkedBuildingCode = String.IsNullOrEmpty(tsr.BuildingcodeGenerated) ? "" : string.Concat(":", tsr.BuildingcodeGenerated);
tsr.GeneratedKey = String.Format("{0}{1}{2}{3}{4}", chekedTitleNumber, chekedMark, checkedMarkSm, checkedBuildingCode, checkedNomenclatureGroupMTOGenerated);
filterdTsrItems.Add(tsr);
});
Вопрос следующий: Нужно ли при выполнении таких переборов объявлять потокобезопасные коллекции(например использовать ConcurrentBag вместо List как в 3 м примере)? Т.е. для первого примера использовать ConcurrentBag startMdrItems, ConcurrentBag sdsItemsGlobal, для второго ConcurrentBag tsrFiltered, ConcurrentBag sdsItems. Выявил проблему с потокобезопасностостью в 3 примере в строчке filterdTsrItems.Add(tsr); когда filterdTsrItems был объявлен через List<> а не через ConcurrentBag<>, отсюда и возникли сомнения по поводу остальных примеров.
ForEach: Prefer ForAll to ForEach when it is possible.ForAllв данном случае действительно лучше. Но только при использовании потокобезопасной коллекции внутри! А если взятьForEach, то коллекциию можно использовать любую. – Alexander Petrov Nov 25 '22 at 08:41