You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在运行时可靠检测动态加载的DLL是否已卸载?

动态加载DLL的卸载检测问题

我在.NET 7 WPF应用中有这样的场景:数据网格列使用用户自定义的C#脚本,用户修改脚本后会编译生成新的DLL,这时候需要卸载旧版本的DLL。

按照官方文档的思路做了测试,用自定义AssemblyLoadContext加载DLL,但遇到了异常情况:

  • 点击Button1调用RunTest方法时,从创建上下文、加载DLL、执行逻辑到卸载的流程是完整的,之后弱引用的IsAlive会变为false,符合预期
  • 但把逻辑拆分成RunTest2和Button2_Click两个阶段后,先创建上下文再执行卸载,弱引用的IsAlive始终为true,不过VS的「Modules」窗口里已经看不到这个DLL了

我想搞清楚:是我对弱引用的使用有误,还是对VS模块窗口的理解有偏差?另外,有没有一种可靠的方法可以检测DLL是否已经被卸载?

测试代码如下:

private void Button1_Click(object sender, RoutedEventArgs e)
{
    var spo = model.GetDataObject(0);
    RunTest(spo, @"dll_2098706330365.dll");  // 正常工作
    RunTest2(spo, @"dll_2098706330365.dll"); // 异常
}
private void Button2_Click(object sender, RoutedEventArgs e)
{
    WeakReference weakRef;
    TestUnload22(alc, out weakRef);
    TestUnload23(weakRef);
}
MyAssemblyLoader alc;
public void RunTest(DataObject spo, string path)
{
    WeakReference weakRef;
    TestUnload(path, spo, out weakRef);

    for (int i = 0; weakRef.IsAlive && (i < 10); i++)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();

        Debug.WriteLine("    >>> UnloadTest: attemtp: {0} Weak ref {1}", i, weakRef.IsAlive);
    }

    Debug.WriteLine(">>> RunTest: ended {0}", weakRef.IsAlive);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void TestUnload(string path, DataObject spo, out WeakReference weakRef)
{
    var alc = new MyAssemblyLoader (path);
    Assembly a = alc.LoadFromAssemblyPath(path);

    weakRef = new WeakReference(alc, trackResurrection: true);

    var scriptInstance = InstantiateScript(a);

    var result = scriptInstance.Evaluate(spo, null)?.ToString();

    Debug.WriteLine("    >>>  Evaluate: " + result);

    alc.Unload();
}
public void RunTest2(ISPDataObject spo, string path)
{
    TestUnload2(path, spo);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void TestUnload2(string path, ISPDataObject spo)
{
    alc = new MyAssemblyLoader (path);
    Assembly a = alc.LoadFromAssemblyPath(path);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void TestUnload22(MyAssemblyLoader alc, out WeakReference weakRef)
{
    weakRef = new WeakReference(alc, trackResurrection: true);
    alc.Unload();
}
private void TestUnload23(WeakReference weakRef)
{
    for (int i = 0; weakRef.IsAlive && (i < 10); i++)
    {
        GC.Collect();
        GC.WaitForPendingFinalizers();

        Debug.WriteLine("    >>> UnloadTest2: attemtp: {0} Weak ref {1}", i, weakRef.IsAlive);
    }

    Debug.WriteLine(">>> RunTest2: ended {0}", weakRef.IsAlive);
}

内容的提问来源于stack exchange,提问作者Boppity Bop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 10:43:31