.NET Remoting Singleton内存泄漏,TCP,Marshal by Reference

mlu*_*sby 6 .net c# remoting memory-leaks marshalling

我正在使用我能找到的最简单的远程处理示例,在Windows服务和Windows窗体程序(客户端)之间共享一个对象,在同一台机器上运行.

该服务实例化对象,如下所示:

serviceConfigRemote = new serviceConfigDataRemote();
serverChannel = new TcpServerChannel(9090);
ChannelServices.RegisterChannel(serverChannel, false);
RemotingServices.Marshal(this.serviceConfigRemote, "ServiceConfigData");
Run Code Online (Sandbox Code Playgroud)

客户端建立如下连接:

TcpClientChannel channel = new TcpClientChannel();
ChannelServices.RegisterChannel(channel, false);
configData = (serviceConfigDataRemote)Activator.GetObject(typeof(serviceConfigDataRemote), "tcp://localhost:9090/ServiceConfigData");
Run Code Online (Sandbox Code Playgroud)

这个想法是服务能够更改对象的某些参数,以便客户端能够读取这些更改.

对象本身是:

public sealed class serviceConfigDataRemote : MarshalByRefObject
{
    private bool myConnectedFlag;
    private bool mySendingFlag;
    private bool myUpdateFlag;
    private string myClientConfiguration;

    static readonly serviceConfigDataRemote instance = new serviceConfigDataRemote();

    static serviceConfigDataRemote()
    {
    }

    public serviceConfigDataRemote()
    {
        myConnectedFlag = false;
        mySendingFlag = false;
        myUpdateFlag = false;
        myClientConfiguration = "";
    }

    public static serviceConfigDataRemote Instance
    {
        get
        {
            return instance;
        }
    }

    public override object InitializeLifetimeService()
    {
        return (null);
    }


    public bool Connected
    {
        get { return myConnectedFlag; }
        set { myConnectedFlag = value; }
    }

    public bool Sending
    {
        get { return mySendingFlag; }
        set { mySendingFlag = value; }
    }

    public bool CheckForUpdates
    {
        get{return myUpdateFlag;}
        set { myUpdateFlag = value; }
    }

    public string ClientConfiguration
    {
        get { return myClientConfiguration; }
        set { myClientConfiguration = value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然服务本身运行,但任务管理器中的Mem Usage保持不变,即使服务不断使用状态信息更新对象.当客户端启动时,两者都开始在Mem Usage中增加,并且永远不会下降.

这是我在My Previous Question中提到的关于发现内存泄漏的问题.

它在不同的机器上显示不同,有些显示没有内存增加,但是这些机器可以可靠地重现这个问题.运行.NET Memory Profiler显示,在服务上,"新实例"的数量不断增加,在选项卡类型/资源中只有一个或两个"已删除",其中命名空间/系统是内核,名称/资源是HeapMemory.我还在努力学习如何使用Memory Profiler,所以如果这是错误的信息,我会道歉,并且我还应该看到我应该寻找的其他地方.

这个对象被实例化一次,只有几个参数可以读写,没有文件io,没有我可以看到的内存分配,但是我的内存使用量似乎只是从我从客户端开始连接到该对象并读取其值.任何和所有输入将不胜感激,因为我想避免拉动此代码并将其替换为命名管道或类似的,但我很快就接近这一点作为我唯一的选择.

Jes*_*cer 3

您的服务不应该在实例化对象的地方,

serviceConfigRemote = new serviceConfigDataRemote();
Run Code Online (Sandbox Code Playgroud)

看起来像

serviceConfigRemote = serviceConfigDataRemote.Instance;
Run Code Online (Sandbox Code Playgroud)

反而?

至少,按照您的方式,您在服务器端创建两个不同的实例,一个在instance属性使用的静态成员初始值设定项中Instance,另一个通过new serviceConfigDataRemote()显式构造创建。向该类添加私有构造函数也可能对您很有帮助,这样除了静态初始化程序之外,没有其他东西可以实例化单例。

这可能不是解决不断增加的内存的方法,但它绝对是一个需要解决的问题。

编辑:

以下是我在网上发现的更多提示:

  • 添加[MTAThread]到宿主服务的main方法中。
  • RemotingServices.Disconnect(this.serviceConfigRemote);当您关闭主机服务时。

希望这可以有所帮助。