C# TCPClient位于单独线程中的内存泄漏
我正在尝试使用以下函数从网络流中读取一些字符串数据:C# TCPClient位于单独线程中的内存泄漏,c#,multithreading,memory-leaks,tcpclient,C#,Multithreading,Memory Leaks,Tcpclient,我正在尝试使用以下函数从网络流中读取一些字符串数据: static TcpClient client; static NetworkStream nwStream; private void conn_start_Click(object sender, EventArgs e) { //Click on conn_start button starts all the connections client = new TcpClient(tcp_ip.Text, Convert
static TcpClient client;
static NetworkStream nwStream;
private void conn_start_Click(object sender, EventArgs e)
{
//Click on conn_start button starts all the connections
client = new TcpClient(tcp_ip.Text, Convert.ToInt32(tcp_port.Text));
nwStream = client.GetStream();
readBuff="";
Timer.Start();
}
string readBuff;
private void readFromConnection()
{
string x1 = "";
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
x1 = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead);
//
//some more code to format the x1 string
//
readBuff = x1;
bytesToRead = null;
GC.Collect();
}
现在,从计时器滴答声事件中每秒调用一次函数readFromConnection(),代码如下:
private void Timer_Tick(object sender, EventArgs e)
{
Thread rT1 = new Thread(readFromConnection);
rT1.Start();
//app crashes after 40-45 min, out of memory exception.
}
这会导致一些内存泄漏。应用程序在运行40-45分钟后崩溃,出现OutOfMemory异常
我的问题是,是否有适当的方法来处理新线程,因为它将只活动1秒?我如何克服这个问题
我必须在一个新的线程中运行这个函数,因为当它与UI在同一个线程上时,它会冻结它。即使是小鼠标的移动也需要几秒钟的时间来处理
从同一角度来看,如果Tick事件调用同一线程中的函数,则不存在内存泄漏问题
private void Timer_Tick(object sender, EventArgs e)
{
readFromConnection();
//No memory leak here.
}
private void readFromConnection()
{
string x1 = "";
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
x1 = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead);
//
//some more code to format the x1 string
//
readBuff = x1;
bytesToRead = null;
nwStream.Flush(); // Add this line
GC.Collect();
}
只需使用
Flush
内存流即可防止内存泄漏
private void Timer_Tick(object sender, EventArgs e)
{
readFromConnection();
//No memory leak here.
}
private void readFromConnection()
{
string x1 = "";
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
x1 = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead);
//
//some more code to format the x1 string
//
readBuff = x1;
bytesToRead = null;
nwStream.Flush(); // Add this line
GC.Collect();
}
另外,使用
定时器
和触发器读取连接
是一种不好的方法。简单地说,使用while
语句读取流 只需使用刷新内存流即可防止内存泄漏
private void Timer_Tick(object sender, EventArgs e)
{
readFromConnection();
//No memory leak here.
}
private void readFromConnection()
{
string x1 = "";
byte[] bytesToRead = new byte[client.ReceiveBufferSize];
int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
x1 = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead);
//
//some more code to format the x1 string
//
readBuff = x1;
bytesToRead = null;
nwStream.Flush(); // Add this line
GC.Collect();
}
另外,使用定时器
和触发器读取连接
是一种不好的方法。简单地说,使用while
语句读取流 不需要计时器
,您可以将接收
逻辑放入一个无限while循环中,并且可以在每次迭代之间为线程添加睡眠指令。您不应该使用ReceiveBufferSize
从套接字流读取数据ReceiveBufferSize
与另一方发送的字节数或可供我读取的字节数不相同。您可以改为使用Available
,即使我从网络读取大文件时也不信任此属性。您可以使用client.client.Receive
方法,此方法将阻止调用线程
private void readFromConnection()
{
while (true)
{
if(client.Connected && client.Available > 0)
{
string x1 = string.Empty;
byte[] bytesToRead = new byte[client.Available];
int bytesRead = client.Client.Receive(bytesToRead);
x1 = System.Text.Encoding.Default.GetString(bytesToRead);
}
Thread.Sleep(500);
}
}
最后,关于GC
看一下不需要计时器
,您可以将接收
逻辑放在一个无限while循环中,并且可以在每次迭代之间为线程添加睡眠指令。您不应该使用ReceiveBufferSize
从套接字流读取数据ReceiveBufferSize
与另一方发送的字节数或可供我读取的字节数不同。您可以改为使用Available
,即使我从网络读取大文件时也不信任此属性。您可以使用client.client.Receive
方法,此方法将阻止调用线程
private void readFromConnection()
{
while (true)
{
if(client.Connected && client.Available > 0)
{
string x1 = string.Empty;
byte[] bytesToRead = new byte[client.Available];
int bytesRead = client.Client.Receive(bytesToRead);
x1 = System.Text.Encoding.Default.GetString(bytesToRead);
}
Thread.Sleep(500);
}
}
最后,关于GC
看一看我有几个问题要问你,你为什么要手动调用GC.Collect()
?为什么要在Timer
Tick事件中创建线程呢?我添加了GC来检查它是否解决了任何内存泄漏问题。起初它不在那里。对于新线程,这样做是为了防止主UI冻结。请告诉我这样做是否不好?您不应该手动调用GC.Collect()
,垃圾收集是为您管理的。您可以通过将逻辑封装在无限while循环中,并在每次迭代之间添加一条睡眠指令来摆脱计时器,这样,您只会得到一个线程。我将简短地添加一个答案。我有几个问题要问您,为什么要手动调用GC.Collect()
?为什么要在Timer
Tick事件中创建线程呢?我添加了GC来检查它是否解决了任何内存泄漏问题。起初它不在那里。对于新线程,这样做是为了防止主UI冻结。请告诉我这样做是否不好?您不应该手动调用GC.Collect()
,垃圾收集是为您管理的。通过将逻辑封装在无限while循环中,并在每次迭代之间添加一条睡眠指令,您可以摆脱计时器。这样,您只会得到一个线程。我将简短地添加一个答案刷新没有对内存泄漏进行任何更改,但更改方法的建议有所帮助。谢谢刷新没有对内存泄漏进行任何更改,但更改方法的建议起到了帮助。谢谢谢谢你的改进。他们都做得很好@chiro3110很高兴我帮了你@马哈茂德非常感谢。它解决了我一周的挣扎。谢谢你的改进。他们都做得很好@chiro3110很高兴我帮了你@马哈茂德非常感谢。它解决了我一周的挣扎。