Я создал это нормально для цикла:
public static Dictionary<string,Dictionary<string,bool>> AnalyzeFiles(IEnumerable<string> files, IEnumerable<string> dependencies)
{
Dictionary<string, Dictionary<string, bool>> filesAnalyzed = new Dictionary<string, Dictionary<string, bool>>();
foreach (var item in files)
{
filesAnalyzed[item] = AnalyzeFile(item, dependencies);
}
return filesAnalyzed;
}
Цикл просто проверяет, имеет ли каждый файл, который находится в переменной «files», все зависимости, указанные в переменной «dependencies».
Переменная "files" должна иметь только уникальные элементы, потому что она используется в качестве ключа для результата, словаря, но я проверяю это перед вызовом метода.
Цикл for работает правильно, и все элементы обрабатываются в одном потоке, поэтому я хотел повысить производительность, переключившись на параллельный цикл for, проблема в том, что не все элементы, которые происходят из переменной «files», обрабатываются в параллельно для (в моем тестовом случае я получаю 30 элементов вместо 53).
Я пытался увеличить временной интервал или удалить весь код «Monitor.TryEnter» и использовать только блокировку (filesAnalyzed), но все равно получил тот же результат
Я не очень знаком с параллелью для, так что это может быть что-то в синтаксисе, который я использую.
public static Dictionary<string,Dictionary<string,bool>> AnalyzeFiles(IEnumerable<string> files, IEnumerable<string> dependencies)
{
var filesAnalyzed = new Dictionary<string, Dictionary<string, bool>>();
Parallel.For<KeyValuePair<string, Dictionary<string, bool>>>(
//start index
0,
//end index
files.Count(),
// initialization?
()=>new KeyValuePair<string, Dictionary<string, bool>>(),
(index, loop, result) =>
{
var temp = new KeyValuePair<string, Dictionary<string, bool>>(
files.ElementAt(index),
AnalyzeFile(files.ElementAt(index), dependencies));
return temp;
}
,
//finally
(x) =>
{
if (Monitor.TryEnter(filesAnalyzed, new TimeSpan(0, 0, 30)))
{
try
{
filesAnalyzed.Add(x.Key, x.Value);
}
finally
{
Monitor.Exit(filesAnalyzed);
}
}
}
);
return filesAnalyzed;
}
Любая обратная связь приветствуется
4 ответа
Перепишите свой обычный цикл следующим образом:
Parallel.Foreach(files, item=>
{
filesAnalyzed[item] = AnalyzeFile(item, dependencies);
});
Вам также следует использовать ConcurrentDictionary , кроме словаря, чтобы сделать весь процесс потокобезопасным
Трудно сказать, что именно идет не так, без отладки кода. Просто глядя на это, я бы использовал ConcurrentDictionary
для переменной filesAnalyzed вместо обычного `Dictionary и избавился бы от Monitor.
Я бы также проверил, существует ли такой же ключ в файлах словаря. Анализируется, возможно, вы пытаетесь добавить kvp с ключом, который уже добавлен в словарь.
Вы можете упростить свой код на много , если вместо этого используете Parallel LINQ:
public static Dictionary<string,Dictionary<string,bool>> AnalyzeFiles(IEnumerable<string> files, IEnumerable<string> dependencies)
{
var filesAnalyzed = ( from item in files.AsParallel()
let result=AnalyzeFile(item, dependencies)
select (Item:item,Result:result)
).ToDictionary( it=>it.Item,it=>it.Result)
return filesAnalyzed;
}
В этом случае я использовал синтаксис кортежа, чтобы избежать шума. Это также сокращает ассигнования.
Используя синтаксис метода, можно записать то же самое, что и:
var filesAnalyzed = files.AsParallel()
.Select(item=> (item, AnalyzeFile(item, dependencies)))
.ToDictionary( it=>it.Item,it=>it.Result)
Dictionary<>
не является поточно-ориентированным для модификации. Если вы хотите использовать Parallel.ForEach
без блокировки, вам придется использовать ConcurrentDictionary
var filesAnalyzed = ConcurrentDictionary<string,Dictionary<string,bool>>;
Parallel.ForEach(files,file => {
filesAnalyzed[item] = AnalyzeFile(item, dependencies);
});
В этом случае, по крайней мере, нет никакого преимущества в использовании Parallel
по сравнению с PLINQ.
Предполагая, что код внутри AnalyzeFile
и dependencies
является потокобезопасным, как насчет чего-то вроде этого:
var filesAnalyzed = files
.AsParellel()
.Select(x => new{Item = x, File = AnalyzeFile(x, dependencies)})
.ToDictionary(x => x.Item, x=> x.File);
Похожие вопросы
Новые вопросы
c#
C # (произносится как «резкий») - это высокоуровневый, статически типизированный язык программирования с несколькими парадигмами, разработанный Microsoft. Код C # обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, включая, среди прочего, .NET Framework, .NET Core и Xamarin. Используйте этот тег для вопросов о коде, написанном на C # или в формальной спецификации C #.