卸载 appdomain 时出错。 (来自 HRESULT 的异常:0x80131015),在 Windows 服务中

Posted

技术标签:

【中文标题】卸载 appdomain 时出错。 (来自 HRESULT 的异常:0x80131015),在 Windows 服务中【英文标题】:Error while unloading appdomain. (Exception from HRESULT: 0x80131015), inside Windows Service 【发布时间】:2012-11-13 17:17:38 【问题描述】:

我在 Windows 服务中收到此错误。 这与我之前在问题here 中讨论过的服务相同

代码被修改为使用Parallel.ForEach(我自己的版本,因为这是一个 3.5 Windows 服务)。并行使用的原因归结为这样一个事实,即卸载每个域并并行运行它们所花费的时间太长,应该证明会更快(似乎即使只有一个线程在执行每个卸载?!)。

根据其他帖子,我只能猜测这是因为我使用ThreadPool ThreadUnloadAppDomains 的事实。我只是看不出如何避免它?

public partial class SomeService : ServiceBase

    private Manager _appDomainManager;

    protected override void OnStop()
    
        _appDomainManager.Dispose();
    


public class Manager : IDisposable

    public void Dispose()
    
        Log.Debug("Disposing");
        Dispose(true);
        GC.SuppressFinalize(this);
    

    protected virtual void Dispose(bool disposing)
    
        if (_disposed) return;
        if (disposing)
        
            // dispose managed resources
            Parallel.For(0, appdomains.Length, UnloadAppDomian);
        

        _disposed = true;
    


private UnloadAppDomain(int appDomainIndex);

public static class Parallel35

    public static void For(int start, int end, Action<int> action)
    
        var waitHandles = new WaitHandle[end - start];
        for (int j = 0; j < waitHandles.Length; j++)
        
            waitHandles[j] = new ManualResetEvent(false);
        

        for (int i = start; i < end; i++)
        
            int i1 = i - start;
            ThreadPool.QueueUserWorkItem(
                state =>
                
                    try
                    
                        action((int) state);
                    
                    finally
                    
                        ((ManualResetEvent) waitHandles[i1]).Set();
                    
                , i);
        
        WaitHandle.WaitAll(waitHandles);
    

【问题讨论】:

您是否尝试过将调试器附加到您的服务,以便使用“线程”窗口准确查看发生这种情况的时间?顺便说一句,您是否尝试过在单个后台任务中卸载所有 AppDomain,而不是为每个 AppDomain 一个后台任务? @PanosRontogiannis 问题是当我在单个后台线程中运行它时,OnStop 的执行时间太长了。仍在对问题进行一些怀疑的调查。 【参考方案1】:

我将此作为错误追踪到退出时等待从未设置的 WaitHandle 的 AppDomains 之一。

如果一个线程没有中止,例如因为它正在执行 非托管代码,或者因为它正在执行 finally 块,然后在 一段时间内会抛出 CannotUnloadAppDomainException 最初调用 Unload 的线程。

AppDomain 现在卸载速度相对较快,我的服务很快停止。

【讨论】:

感谢这条五年前的消息,我通过用可调用的清理例程替换两个析构函数块解决了我自己的异常,以便在我清洗完成后但在对象被销毁之前卸载 AppDomain。 @David A. Gray 你能分享你的解决方案吗?【参考方案2】:

尝试在单个后台任务中卸载所有 AppDomain,而不是为每个 AppDomain 一个后台任务,并使用ServiceBase.RequestAdditionalTime,以便 SCM 不会将您的服务标记为无响应。

【讨论】:

以上是关于卸载 appdomain 时出错。 (来自 HRESULT 的异常:0x80131015),在 Windows 服务中的主要内容,如果未能解决你的问题,请参考以下文章

AppDomain.Unload 问题

卸载 appdomain 不会清除 C++ COM 对象静态成员

通过应用程序域AppDomain加载和卸载程序集

ASP.NET Web 应用程序在部署后不卸载 AppDomains

AppDomain 详解二-C#中动态加载和卸载DLL

即使我卸载 appdomain,我的 dll 也不会卸载