4

我在使用 DllImport 和 ASP.NET 时遇到了一些问题,因为当我使用导入的方法时,ASP.NET 会加载 Dll 并锁定文件,即使它完成使用后也是如此。有没有办法强制 ASP.NET 释放文件上的锁定?

4

3 回答 3

2

在 .Net 中强制 DLL 退出进程的唯一方法是卸载加载 Dll 的 AppDomain。除非您创建一个单独的 AppDomain 在其中运行 DllImport 代码,否则这是不可能的。

我也知道这个政策适用于托管 DLL。我不是 100% 确定这是否适用于通过 PINvoke 加载的 DLL,但我相当确定。

于 2009-04-07T14:40:56.307 回答
2

仅当您创建新的 AppDomain 并将 dll 加载到域中时。之后你可以卸载 AppDomain 并且 dll 将被卸载。

于 2009-04-07T14:42:09.843 回答
0

卸载 AppDomain 并不是唯一的答案。您还可以使用LoadLibraryFreeLibraryover pinvoke 来卸载库。只需确保您调用FreeLibrary了两次以确保您的库的任何依赖项也被卸载。

我没有对此进行测试,但我想像这样的课程会让这样做更容易:

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string libname);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool FreeLibrary(IntPtr hModule);

class LibraryHandle
{
    readonly string libName;
    int refCount = 0;
    IntPtr handle;

    public LibraryHandle(string name)
    {
        libName = name;
    }

    public void Increment()
    {
        if (refCount == 0)
        {
            handle = LoadLibrary(libName);
            if (Handle == IntPtr.Zero)
            {
                int error = Marshal.GetLastWin32Error();
                throw new Exception(string.Format("{0})", error));
            }
        }
        ++refCount;
    }

    public void Decrement()
    {
        if (refCount <= 0)
            return;

        if (--refCount)
        {
            // It might be better in some cases to:
            // while(FreeLibrary(handle));
            FreeLibrary(handle);
            FreeLibrary(handle);
        }
    }
}

请注意,此示例不是线程安全的,您需要在 ASP.NET 中保证这一点,并且不会进行完整的错误检查。

此外,由于这可能违反运行时所做的一些假设,因此FreeLibrary在您未加载的库上使用可能不是一个好主意。

另一种选择是在 new 中执行任何操作,AppDomain然后在完成后将其卸载。

于 2015-04-01T16:23:27.673 回答