【问题标题】:Is Assembly.Load(byte[]) not thread safe?Assembly.Load(byte[]) 不是线程安全的吗?
【发布时间】:2012-02-10 05:43:56
【问题描述】:

我附加到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");
    }
}

【问题讨论】:

    标签: .net assemblies


    【解决方案1】:

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

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

    鉴于本主题中的早期信息,我觉得有必要定义线程安全(根据wikipedia):

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

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

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

    【讨论】:

      【解决方案2】:

      查看这些方法的实现细节,您可以证明 LoadFrom 和 LoadFile 方法,因为它们使用文件系统,所以在那里有它们的同步。也就是说,这两种方法都在读入文件之前获得了一个排他锁。当然,程序集不是驻留在内存中的情况。

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

      【讨论】:

      • msdn.microsoft.com/en-us/library/… 提到类型(Assembly)是线程安全的。所以这将表明整个类型,包括 Assembly.Load(byte[]) 确实是线程安全的。
      • “线程安全”是一个相当没有意义的术语,因为很少有文档说明“安全”行为将是什么。有时,“线程安全”仅意味着“从多个线程访问时不会崩溃”,但我们几乎总是需要更多关于行为的知识。也许从字节数组加载程序集是安全的,因为您有时会得到重复,但永远不会崩溃,这就是文档的含义。通常只有“并发”数据结构类记录安全行为将是什么。
      • Lasse,在我的场景中,我从并发场景中加载不同的程序集。线程安全根本不是一个毫无意义的术语。我可以解释和验证其他变量。如果它确实不是线程安全的,那么我必须从异步读取操作中维护一个线程安全的集合,将字节数组添加到其中,然后循环遍历它,一个一个地添加程序集。
      猜你喜欢
      • 2014-02-07
      • 2010-10-15
      • 2016-07-17
      • 1970-01-01
      • 2021-10-12
      • 2015-04-18
      • 2011-10-07
      • 2012-03-02
      • 2011-10-28
      相关资源
      最近更新 更多