我们有一个C#应用程序,它连接到FTP服务器,下载一些文件,断开连接并在一段时间后(由用户通过UI选择)重新连接并重复该过程。我们使用BackgroundWorker实现了这个功能,但我们注意到,在运行更长时间之后,程序停止记录其操作,无论是在UI还是日志文件中。 那时,没有文件要下载,所以我们上传了一些文件,它恢复了活动,就好像什么都没发生过一样。线程停止工作
问题是,普通用户无法知道该程序仍在工作,所以我们决定使用自己的线程来实现它。我们做了一个更简单的程序,排除其他任何问题,并且这个程序只连接到FTP并断开连接。它停止显示消息,就像BackgroundWorker一样(2小时后一次,22小时后一次,没有任何我们可以找到的模式,并且在没有其他任何事情的计算机上)。
DoFTPWork += new DoFTPWorkDelegate(WriteFTPMessage);
FTPWorkThread = new Thread(new ParameterizedThreadStart(Process));
//seData is the FTP login info
FTPWorkThread.Start(seData);
和FTP方法是:
private void Process(object seData1)
{
seData = (SEData)seData1;
while (!stopped)
{
try
{
ftp = null;
ftp = new FTP_Client();
if (ftp.IsConnected)
{
logMessages += DateTime.Now + "\t" + "info" + "\t" + "Ftp disconnected from " + seData.host + "\r\n";
ftp.Disconnect();
}
ftp.Connect(seData.host, 21);
ftp.Authenticate(seData.userName, seData.password);
logMessages += DateTime.Now + "\t" + "info" + "\t" + "Ftp connected to " + seData.host + "\r\n";
error = false;
logMessages += DateTime.Now + "\t" + "info" + "\t" + "Trying to reconnect in 5 seconds\r\n";
System.Threading.Thread.Sleep(5000);
SlaveEventArgs ev = new SlaveEventArgs();
ev.Message = logMessages;
txtLog.Invoke(DoFTPWork, ev);
System.Threading.Thread.Sleep(200);
logMessages = "";
}
catch (Exception ex)
{
logMessages = "";
if (ftp.IsConnected)
{
ftp.Disconnect();
}
ftp.Dispose();
logMessages += DateTime.Now + "\t" + "ERR" + "\t" + ex.Message + "\r\n";
logMessages += DateTime.Now + "\t" + "info" + "\t" + "Trying to reconnect in 5 seconds\r\n";
SlaveEventArgs ev = new SlaveEventArgs();
ev.Message = logMessages;
txtLog.Invoke(DoFTPWork, ev);
System.Threading.Thread.Sleep(5 * 1000);
error = true;
}
}
}
WriteFTPMessage在TextBox显示消息并在原始程序中写为.txt文件。
+1为资源泄漏部分。如果有很多活动连接,可能很容易达到(可能很小)限制并导致挂起。 – 2009-01-12 07:38:03
我们进行了一次重组,此外,我们每隔100行就清除UI中的日志文本框,并且客户没有再报告任何冻结。 – Rox 2009-11-20 07:12:05