3

我在我的项目中使用 Unity 2.0,我在 Parallel.ForEach 代码块中同时读取大量文件:

Parallel.ForEach(files, currentFile =>
{
    using(IMsBuildProjectLoader msBuildProject = Container.Resolve<IMsBuildProjectLoader>(new ParameterOverride("projectFileName", currentFile)))
    {
        // file processing
    }
}

Resolve(new ParameterOverride("projectFileName", currentFile) 函数有时会抛出 ResolutionFailedException:

ResolutionFailedException: Resolution of the dependency failed, 
type = "Porthus.Build.Common.Interfaces.IMsBuildProjectLoader", name = "(none)". 
Exception occurred while: Calling constructor XXX.Build.Common.Types.MsBuildProjectLoader(System.String projectFileName). 
Exception is: ArgumentException - Item has already been added. Key in dictionary: 'xxx'  Key being added: 'xxx'

这是同时加载同一个文件的时候 - Resolve 函数正在同时创建两个具有相同参数的 IMsBuildProjectLoader 实例。它无法通过 files.Distinct() 过滤器解决。上面的代码只是解释我的问题的代码示例。

问题是:如何实现线程安全的 UnityContainer.Resolve 函数?是否可以使用一些 Unity 扩展类来做到这一点?

IMsBuildProjectLoader

public interface IMsBuildProjectLoader : IDisposable
{
}

MsBuildProjectLoader

public class MsBuildProjectLoader : Project, IMsBuildProjectLoader
{
    public MsBuildProjectLoader(string projectFileName)
        : base()
    {
        // Load the contents of the specified project file.
        Load(projectFileName);
    }
}

MsBuildProjectLoader 是这样注册的:

container.RegisterType<IMsBuildProjectLoader, MsBuildProjectLoader>();
4

1 回答 1

0

Resolve 实际上是线程安全的(或者微软 P&P 的人这么说)。可能不是线程安全的是MsBuildProjectLoader的实现,或者更具体地说,它是构造函数。通过以相同的异步方式使用new创建 MsBuildProjectLoader 的新实例,您可能会遇到同样的问题

您没有包括 Load 的实现,但根据例外情况,我假设它以非线程安全的方式操作共享或静态字典。如果是这种情况,您应该使该字典线程安全(例如,将其替换为ConcurrentDictionary)。

于 2014-12-21T15:12:40.213 回答