【发布时间】:2023-03-21 17:37:01
【问题描述】:
我正在尝试使用以下函数从网络流中读取一些字符串数据:
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() 函数每秒从 Timer Tick 事件调用,代码如下:
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.
}
【问题讨论】:
-
我有几个问题要问你,你为什么要手动拨打
GC.Collect()?为什么要在TimerTick Event 中创建线程? -
我添加了 GC 来检查它是否解决了任何内存泄漏问题。最初它不存在。对于新线程,这样做是为了防止主 UI 冻结。如果这样做是不好的方法,请告诉我?
-
你不应该手动调用
GC.Collect(),垃圾收集是为你管理的。你可以通过将你的逻辑包装在一个无限的while循环中来摆脱定时器,并在每次迭代之间添加一个睡眠指令,这样你就只剩下一个线程了。 -
我会尽快添加答案
标签: c# multithreading memory-leaks tcpclient