在我的物体上神秘地召唤

时间:2012-01-26 13:27:22

标签: c# .net wcf

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

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

public class LogService : ILogProvider
{
    private ServiceHost host;

    public void Open()
    {
        // Open Service
    }

    public void Dispose()
    {
        // host.Dispose();
    }
}

此对象被引用为某个其他类的字段。

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

但是,我看到正在调用LogService的Dispose()方法,虽然我不会在我的代码库中直接调用它!

调试这个,Visual Studio“Call Stack”中的调用者是“外部”,所以我无法查看它。

这会导致什么?在调用它时,host字段为null,并抛出null引用。

这是失败的问号:

  
    

Executer.dll!Executer.LogService.Dispose()第54行+ 0x6字节C#System.ServiceModel.dll!System.ServiceModel.Dispatcher.InstanceBehavior.InstanceProvider.ReleaseInstance(System.ServiceModel.InstanceContext     instanceContext,object instance)+ 0x25 bytes
      System.ServiceModel.dll!System.ServiceModel.Dispatcher.InstanceBehavior.ReleaseInstance(System.ServiceModel.InstanceContext     instanceContext,object instance)+ 0x35 bytes
      System.ServiceModel.dll!System.ServiceModel.InstanceContext.SetUserObject(对象     newUserObject)+ 0x4e bytes
      System.ServiceModel.dll!System.ServiceModel.InstanceContext.Unload()     + 0xf bytes 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 bytes System.ServiceModel.dll!System.ServiceModel.InstanceContext.NotifyEmpty(System.ServiceModel.InstanceContext     instanceContext)+ 0xb bytes
      System.ServiceModel.dll!System.ServiceModel.ServiceChannelManager.OnEmpty()     + 0x16字节System.ServiceModel.dll!System.ServiceModel.Channels.LifetimeManager.DecrementBusyCount()     + 0xbc bytes 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 bytes
      System.ServiceModel.dll!System.ServiceModel.Channels.CommunicationObject.OnClosed()     + 0xd5 bytes System.ServiceModel.dll!System.ServiceModel.Channels.CommunicationObject.Abort()     + 0xcf bytes System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.OnInnerChannelFaulted(object     sender,System.EventArgs e)+ 0x46 bytes

  

1 个答案:

答案 0 :(得分:0)

我没有你的答案,但有这个想法。你可能是对的。这意味着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

希望这有助于您朝着正确的方向前进。如果你解决了,请提供答案。