Assembly.Load(byte [])不是线程安全的吗?

时间:2012-02-10 05:43:56

标签: .net assemblies

我附加到AppDomain.AssemblyResolve事件,然后调用Assembly.Load(byte[])加载程序集。

似乎如果这是从多个线程完成的,我最终可能会加载重复的程序集。但是,如果我拨打Assembly.LoadFromAssembly.LoadFile,则不会出现此问题。

我只是想知道这是否是使用Assembly.Load的已知qwerk?它不是线程安全的,我需要添加额外的代码来处理这种情况吗?

完整代码如下......

[TestFixture]
public class Tester
{
    [Test]
    public void Run()
    {
        var currentDomain = AppDomain.CurrentDomain;
        currentDomain.AssemblyResolve += ResolveAssembly;

        var thread1 = new Thread(LoadAssembly);
        var thread2 = new Thread(LoadAssembly);

        thread1.Start();
        thread2.Start();
        thread1.Join();
        thread2.Join();
        var assemblies = currentDomain.GetAssemblies();
        Assert.AreEqual(1, assemblies.Count(x => x.GetName().Name == "AssemblyToReference"));
    }

    Assembly ResolveAssembly(object sender, ResolveEventArgs args)
    {
        //This works
        //return Assembly.LoadFile(@"PathToAssembly");

        //This works
        //return Assembly.LoadFrom(@"PathToAssembly");

        //This does not work
        return Assembly.Load(File.ReadAllBytes(@"PathToAssembly"));
    }

    void LoadAssembly()
    {
        Assembly.Load("AssemblyToReference");
    }
}

2 个答案:

答案 0 :(得分:1)

文档确实表明多次加载同一个程序集可能会导致副本/新实例,所以我绝对不会在同一个程序集或程序集的不同版本上调用它两次。

除此之外,https://msdn.microsoft.com/en-us/library/system.reflection.assembly(v=vs.110).aspx提到类型(程序集)是线程安全的。这样就表明整个类型,包括Assembly.Load(byte [])确实是线程安全的。

鉴于本主题中的更多信息,我认为需要定义线程安全(根据wikipedia):

  • 线程安全:当多个线程同时访问时,保证实现没有竞争条件。

这意味着您可以安全地从多个线程中使用它,但您应该知道该操作不是 idempotent ;两次调用会留下两个结果,而不是一个。

从概念上讲,如果以上是一个问题,使用 Assembly.Load(byte [])的代码实际上不是线程安全的。

答案 1 :(得分:-1)

查看这些方法的实现细节,您可以假设LoadFrom和LoadFile方法由于使用文件系统而在那里进行同步。也就是说,两种方法在读取文件之前都会对文件进行独占锁定。当然,组件驻留在内存中的情况并非如此。

(并且MSDN没有声明这些方法是线程安全的,也许这说得足够了?:))