即使释放了所有成员,垃圾收集器也不会检测到对象.TcpClient与此有关吗
本文关键字:检测 对象 与此有关 TcpClient 收集器 放了 释放 成员 | 更新日期: 2023-09-27 17:58:12
我知道发布长墙的代码是不好的,但这个问题看起来像是一个"浏览并看到一些东西"的问题。
我有一个名为Client的类,它包含了TcpClient所需的所有功能。它在自己的线程上运行,并在调用时使用由Dispose()触发的killSwitch变量。
我的问题是,即使在调用Dispose并丢失对该对象的引用之后,GC仍然不会捕获该对象,也不会删除该对象。
我如何测试对象创建/删除的示例:
private void TESTButton_Click(object sender, EventArgs e)
{
System.Net.Sockets.TcpClient tcp = new System.Net.Sockets.TcpClient();
tcp.Connect("127.0.0.1",3005);
Client c = new Client(tcp, this);
}
类别定义:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Windows.Forms;
namespace v1_GameServer.GameServer
{
public class Client : IDisposable
{
private Boolean gotCommunicatedInfo = false;
private String username = "";
private String password = "";
private String ipAddress;
private GameServerWindow window;
private Boolean isDead;
private static Int32 BUFF_SIZE = 1000;
private byte[] buffer = new byte[BUFF_SIZE];
private TcpClient connection;
private NetworkStream stream;
private Boolean thisThread_killSwitch = false;
private readonly Thread thisThread;
private List<object> packages = new List<object>();
private object packages_lock = new object();
private Client()
{ }
public Client(TcpClient _connection, GameServerWindow win)
{
connection = _connection;
stream = connection.GetStream();
window = win;
ipAddress = ((IPEndPoint)connection.Client.RemoteEndPoint).Address.ToString();
isDead = false;
thisThread = new Thread(new ThreadStart(HandleConnection));
thisThread.Start();
window.Post("+Client : " + ipAddress);
}
~Client()
{
MessageBox.Show("TEST!");
if (window != null)
window.Post("-Client : " + ipAddress);
}
public void HandleConnection()
{
try
{
while (!thisThread_killSwitch && !isDead)
{
int numBytes = stream.Read(buffer, 0, BUFF_SIZE);
if (numBytes > sizeof(Int32)) //Big enough to hold at least a type of message.
{
object newPackage = Package_Reader.ReadPackage(buffer, numBytes);
if (gotCommunicatedInfo == false)
{
if (newPackage is Package_Login_s)
{
username = ((Package_Login_s)newPackage).username;
password = ((Package_Login_s)newPackage).password;
gotCommunicatedInfo = true;
}
else
{
throw new InvalidOperationException("Received a package that was not login info from a new Client.");
}
}
else //(communicatedInfo == true)
{
lock (packages_lock)
{
if (newPackage != null)
packages.Add(newPackage);
}
}
}
else if (numBytes == 0)
{
Dispose();
}
}
}
catch (ObjectDisposedException e)
{
window.Post(ManagerForm.post_CLIENT_ERROR + "Client disconnected.");
isDead = true;
}
catch (InvalidOperationException e)
{
window.Post(ManagerForm.post_CLIENT_ERROR + e.ToString());
isDead = true;
}
}
public object GetPackage()
{
lock (packages_lock)
{
if (packages.Count > 0)
{
object pac = packages[packages.Count - 1];
packages.RemoveAt(packages.Count - 1);
return pac;
}
else
return null;
}
}
public String GetUsername()
{
return (String)username.Clone();
}
public String GetPassword()
{
return (String)password.Clone();
}
public Boolean GetGotCommunicatedInfo()
{
return gotCommunicatedInfo;
}
public Boolean GetIsDead()
{
return isDead;
}
public String GetIP()
{
return (String)ipAddress.Clone();
}
public void Dispose()
{
thisThread_killSwitch = true;
isDead = true;
stream.Dispose();
stream.Close();
connection.Close();
stream = null;
connection = null;
window = null;
}
}
}
您没有在Client
类上正确实现IDisposable
模式。您应该实现的模式是:
public class Foo : IDisposable
{
private bool _disposed;
~Foo()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// Dispose of managed resources
}
// Dispose of unmanaged resources
_disposed = true;
}
}
}
这样,无论是否调用Dispose()
,TcpClient
实例最终都会被清理,不会导致资源泄漏。