c# – FTP upload – memory leak problem – Education Career Blog

I’m working on a personal project that uploads and downloads big files using FTP protocol. It’s working fine except the memory leak that I recently noticed. I don’t know exactly what the problem is. It could be memory leak or bad programming. The memory amount used by this application increasing every second while uploading. Here is the code:

    Action action;
    int bufferSize = 16384;
    EventLogger elog = new EventLogger();
    string error = "";
    string filename = "";

    public Uploader(Action action)
    {
        this.action = action;
        filename = action.directory.Substring(action.directory.LastIndexOf('\\') + 1,
            action.directory.Length - action.directory.LastIndexOf('\\') - 1);
    }

    public bool startUpload()
    {   
        try
        {
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://*******");
            request.Method = WebRequestMethods.Ftp.ListDirectory;
            request.Credentials = new NetworkCredential("***", "***");

            FtpWebResponse response = (FtpWebResponse)request.GetResponse();

            Stream responseStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(responseStream);
            List<string> files = new List<string>();
            string filesArr = reader.ReadToEnd().Split('\n');
            reader.Close();
            response.Close();
            foreach (string file in filesArr)
                files.Add(file.Replace("\r", ""));
            if (files.IndexOf(filename) != -1)
            {
                request = (FtpWebRequest)WebRequest.Create("ftp://***/"+filename);
                request.Method = WebRequestMethods.Ftp.DeleteFile;
                request.Credentials = new NetworkCredential("***", "***");
                response = (FtpWebResponse)request.GetResponse();
                reader.Close();
                response.Close();
                if (response.StatusCode != FtpStatusCode.FileActionOK)
                {
                    return false;
                }
            }

            request = (FtpWebRequest)WebRequest.Create("ftp://***/"+filename);
            request.Method = WebRequestMethods.Ftp.UploadFile;
            request.KeepAlive = false;
            request.UseBinary = true;

            FileStream stream = File.OpenRead(action.directory);
            byte buffer = new bytebufferSize;
            Stream reqStream = request.GetRequestStream();

            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "update DIRECT_UPLOAD set COMPLETED = @com, PROGRESS = @prog, SPEED = @speed where ID = @id";
            cmd.Parameters.AddWithValue("@id", action.id);
            cmd.Parameters.AddWithValue("@com", 0);
            cmd.Parameters.AddWithValue("@prog", 0);
            cmd.Parameters.AddWithValue("@speed", 0);


            long i = 0;
            int readed = 0;
            int total = 0;
            int speed = 0;
            DateTime last = DateTime.Now;
            int lastTotal = 0;
            while ((readed = stream.Read(buffer, 0, bufferSize)) > 0)
            {
                reqStream.Write(buffer, 0, readed);
                total += readed;
                if (i % 100 == 0)
                {
                    cmd.Parameters"@com".Value = total;
                    cmd.Parameters"@prog".Value = (int)(((double)total / action.size) * 100);
                    int tot = 0;
                    tot = total - lastTotal;
                    int time = Convert.ToInt32((DateTime.Now - last).TotalMilliseconds);
                    speed = (int)(((double)1000.0 / time) * tot);
                    cmd.Parameters"@speed".Value = speed;
                    if ((error = SqlProcess.sqlNonQuery(cmd)) != "")
                        throw new Exception(error);
                    last = DateTime.Now;
                    lastTotal = total;
                }

                Application.DoEvents();
                i++;
            }

            cmd.Parameters"@com".Value = total;
            cmd.Parameters"@prog".Value = 100;
            cmd.Parameters"@speed".Value = 0;
            if ((error = SqlProcess.sqlNonQuery(cmd)) != "")
                throw new Exception(error);

            reqStream.Close();
            stream.Close();
        }
        catch (Exception ex)
        {
            elog.write(ex);
            return false;
        }
        return true;
    }

Thank you.

,

Check all the objects you use here to make sure they do not need to be Dispose-d (i.e. do they implement IDisposable?). Otherwise, you will experience a leak of unmanaged resources associated with each of those objects every time this code executes.

You can use using to tidily ensure that Dispose() is called for such objects, in an exception-safe way.

Example – instead of:

SqlCommand cmd = new SqlCommand();

use this to wrap the code that uses cmd

using (SqlCommand cmd = new SqlCommand())
{
}

Note that your EventLogger class may also need to implement IDisposable if it’s a custom class that wraps unmanaged resources through (for example) File or EventLog.

You can check the other built-in classes that you use here and elsewhere in your program in the MSDN docs.

Leave a Comment