我正在尝试使用以下函数从网络流中读取一些字符串数据:
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();
}
现在,使用以下代码从Timer Tick事件中每秒调用 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.
}
答案 0 :(得分:2)
不需要Timer
,您可以将Receive
逻辑置于一个无限循环内,并且可以在每次迭代之间为线程添加睡眠指令。您不应该使用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
,请查看this question
答案 1 :(得分:1)
只需使用bt
内存流来防止内存泄漏。
Flush
此外,使用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();
}
和触发器Timer
是不好的方法。简单地说,使用readFromConnection
语句来读取流。