3

希望有人能指出我在这里做错了什么。我有一个读取文件访问规则的进程,我正在尝试并行运行它。

这是我到目前为止的代码:

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 =>

但仍然没有喜悦。

那么,我做错了什么?提前致谢。

4

1 回答 1

5

传递authorizationRuleCollection.OfType<AuthorizationRule>()Parallel.ForEach,例如:

var typedColletion=authorizationRuleCollection.OfType<AuthorizationRule>();
Parallel.ForEach(typedColletion);

错误是因为AuthorizationRuleCollection没有实现IEnumerable<T>而只有IEnumerable,其元素是Object。当泛型不可用时,这是旧(.NET 2.0 之前)集合的常见模式。

较新的 .NET 类返回/期望泛型集合。通过调用OfType<T>()orCast<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;
        }
    }
于 2015-09-21T09:13:40.680 回答