Hopefully someone could point out what I am doing wrong here. I have a process that reads in file access rules and I am trying to run it in Parallel.
Here is the code I have so far:
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();
}
Which (to the untrained eye), looks like it should work. But the Parallel.ForEach will not compile as it gives the error:
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.
I have also tried changing the offending line to:
Parallel.ForEach<FileSystemAccessRule>( authorizationRuleCollection, fsar =>
But still no joy.
So, what am I doing wrong? Thanks in advance.
Pass
authorizationRuleCollection.OfType<AuthorizationRule>()toParallel.ForEach, eg:The error is caused because
AuthorizationRuleCollectiondoesn't implementIEnumerable<T>but onlyIEnumerable, whose elements areObject. This is a common pattern with older (pre - .NET 2.0) collections, when generics weren't available.Newer .NET classes return/expect generic collections. By calling
OfType<T>()orCast<T>()you effectively cast the sourceIEnumerableto anIEnumerable<T>.The difference is that
OfType<T>()will filter out incompatible elements, whileCast<T>()will throw if any incompatible elements are found.The code behind both methods isn't magic, in the reference source it's simply an iterator over the source
IEnumerable: