Parallel.ForEach over AuthorizationRuleCollection
Надеюсь, кто-то может указать, что я делаю здесь не так. У меня есть процесс, который читает в правилах доступа к файлам, и я пытаюсь запустить его параллельно.
Вот код, который у меня есть:
public List<FolderAccessRule> GetSecurityGroupsForFolder(long importId, string subdirectory, bool includeInherited)
{
ConcurrentQueue<FolderAccessRule> groups = new ConcurrentQueue<FolderAccessRule>();
ConcurrentQueue<Exception> exceptions = new ConcurrentQueue<Exception>();
DirectoryInfo dInfo = new DirectoryInfo(subdirectory);
DirectorySecurity dSecurity = dInfo.GetAccessControl();
AuthorizationRuleCollection authorizationRuleCollection = dSecurity.GetAccessRules(true, includeInherited, typeof(NTAccount));
Parallel.ForEach( authorizationRuleCollection,
fsar =>
{
try
{
FolderAccessRule group = this.GetGroup(fsar);
if (group != null)
{
groups.Enqueue(group);
}
}
catch (Exception e)
{
exceptions.Enqueue(e);
}
});
foreach (Exception e in exceptions)
{
string message = string.Concat(e.GetType(), "Exception getting Directory info for ", subdirectory);
this.RecordException(message, subdirectory, e);
}
return groups.ToList();
}
Который (для неподготовленного глаза), похоже, должен работать. Но Parallel.ForEach
не скомпилируется, так как выдает ошибку:
The type arguments for method 'System.Threading.Tasks.Parallel.ForEach<TSource>
(System.Collections.Generic.IEnumerable<TSource>, System.Action<TSource>)' cannot be inferred from the usage.
Try specifying the type arguments explicitly.
Я также попытался изменить оскорбительную строку на:
Parallel.ForEach<FileSystemAccessRule>( authorizationRuleCollection, fsar =>
Но все равно нет радости.
Итак, что я делаю не так? Заранее спасибо.
1 ответ
Проходить authorizationRuleCollection.OfType<AuthorizationRule>()
в Parallel.ForEach
Например:
var typedColletion=authorizationRuleCollection.OfType<AuthorizationRule>();
Parallel.ForEach(typedColletion);
Ошибка вызвана тем, что AuthorizationRuleCollection
не реализует IEnumerable<T>
но только IEnumerable
чьи элементы Object
, Это обычный шаблон для более старых (до.NET 2.0) коллекций, когда генерики не были доступны.
Новые классы.NET возвращают / ожидают общие коллекции. По телефону OfType<T>()
или же Cast<T>()
вы эффективно применяете источник IEnumerable
для IEnumerable<T>
,
Разница в том, что OfType<T>()
будет отфильтровывать несовместимые элементы, в то время как Cast<T>()
бросит, если будут найдены какие-либо несовместимые элементы.
Код, стоящий за обоими методами, не магический, в ссылочном источнике это просто итератор над источником IEnumerable
:
public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source) {
if (source == null) throw Error.ArgumentNull("source");
return OfTypeIterator<TResult>(source);
}
static IEnumerable<TResult> OfTypeIterator<TResult>(IEnumerable source) {
foreach (object obj in source) {
if (obj is TResult) yield return (TResult)obj;
}
}