Dispose神秘地调用了我的对象

本文关键字:我的 对象 调用 Dispose | 更新日期: 2023-09-27 18:21:25

我遇到了一个奇怪的问题:

我有一个对象(在简化视图中)看起来像这样:

public class LogService : ILogProvider
{
    private ServiceHost host;
    public void Open()
    {
        // Open Service
    }
    public void Dispose()
    {
        // host.Dispose();
    }
}

此对象正被引用为其他类上的字段。

偶尔在我的应用程序中,我会重新创建服务(我想这会导致LogService对象被收集)。

然而,我看到LogService的Dispose()方法正在被调用,尽管我在代码库中没有直接调用它!

调试时,Visual Studio中的调用程序"调用堆栈"是"外部"的,因此我无法查看它。

是什么原因造成的?当调用它时,host字段为null,并抛出一个nullreference。

以下是失败的调用堆栈:

Executer.dll!Executer.LogService.Dispose()行54+0x6字节C#System.ServiceModel.dll!System.ServiceModel.Dispatcher.InstanceBehavior.InstanceProvider.ReleaseInstance(System.ServiceModel.InstanceContextinstanceContext,对象实例)+0x25字节
System.ServiceModel.dll!System.ServiceModel.Dispatcher.InstanceBehavior.ReleaseInstance(System.ServiceModel.InstanceContextinstanceContext,对象实例)+0x35字节
System.ServiceModel.dll!System.ServiceModel.InstanceContext.SetUserObject(对象newUserObject)+0x4e字节
System.ServiceModel.dll!System.ServiceModel.InstanceContext.Unload()+0xf字节System.ServiceModel.dll!System.ServiceModel.InstanceContext.OnClose(System.TimeSpan超时)+0x1f字节
System.ServiceModel.dll!System.ServiceModel.Channels.CommunicationObject.Close(System.TimeSpan超时)+0x172字节
System.ServiceModel.dll!System.ServiceModel.InstanceContext.CloseIfNotBusy()+0x76字节System.ServiceModel.dll!System.ServiceModel.InstanceContext.NotifyEmpty(System.ServiceModel.InstanceContextinstanceContext)+0xb字节
System.ServiceModel.dll!System.ServiceModel.ServiceChannelManager.OnEmpty()+0x16字节System.ServiceModel.dll!System.ServiceModel.Channels.LifetimeManager.DecrementBusyCount()+0xbc字节System.ServiceModel.dll!System.ServiceModel.ServiceChannelManager.ChannelRemoved(System.ServiceModel.Channels.IChannel通道)+0x37字节
System.ServiceModel.dll!System.ServiceModel.ServiceChannelManager.RemoveChannel(System.ServiceModel.Channels.IChannel通道)+0x42字节
System.ServiceModel.dll!System.ServiceModel.ServiceChannelManager.OnChannelClosed(对象sender,System.EventArgs args)+0x16字节
System.ServiceModel.dll!System.ServiceModel.Channels.CommunicationObject.OnClosed()+0xd5字节System.ServiceModel.dll!System.ServiceModel.Channels.CommunicationObject.Artrt()+0xcf字节System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.OnInnerChannelFaulted(对象发送方,System.EventArgs e)+0x46字节

Dispose神秘地调用了我的对象

我没有答案,但有这样的想法。你可能是对的。这意味着ServiceHost在LogService之前被释放。

如果这是真的,那么我不明白为什么LogService中的ServiceHost为null。只有当ServiceHost的处理也会使所有对它的引用无效时,才能做到这一点。我觉得很难相信,但也可能是我缺乏知识(也许有人可以证实)。所以我创建了一个小测试,它应该通过抛出一个null引用异常来验证这一点,但它没有。

public interface ILogProvider : IDisposable
{
    void Open();
}
public class LogService : ILogProvider
{
    private readonly ServiceHost host;
    public LogService(ServiceHost host)
    {
        this.host = host;
    }
    public void Open()
    {
        // Open Service
    }
    public void Dispose()
    {
        host.Dispose();
    }
}
public class ServiceHost : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    ~ServiceHost()
    {
        Dispose(false);
    }
    public virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            //do managed cleanup
        }
        // do unmanaged cleanup here            
    }
}
internal class Program
{
    private static void Main(string[] args)
    {
        var host = new ServiceHost();
        using (LogService log = new LogService(host))
        {
            host.Dispose();
        }
    }
}

测试首先处理ServiceHost,然后在不引发异常的情况下调用对LogService的处理。因此,除非ServiceHost的处理从根本上以不同的方式实现(这很容易),否则您必须检查LogService是如何创建的。它真的总是引用ServiceHost吗?

希望这能帮助你朝着正确的方向前进。此外,如果您解决了问题,请提供答案。