我目前在c#中的內存使用量正在掙扎。字節的空閒內存[]
我目前正在使用的工具能夠上傳和下載文件。爲此,它使用字節數組作爲文件內容的緩衝區。在上傳或下載操作後,我可以放棄WebResponse和Stream(+ Reader/Writer)對象,但字節數組永遠保持在內存中。它超出了範圍,我甚至'空'它,所以我猜垃圾收集從未運行。
在搜索過程中,我發現了很多文章,建議永遠不要手動運行GC,但有一個簡約的後臺應用程序,不斷佔用100或甚至1000 MB的RAM(使用時間越長,什麼都不過分。
那麼,如果不推薦使用GC,那麼在這種情況下還能做什麼呢?
編輯3 /解決方案:我結束了使用從文件I/O填充數據的16kb字節緩衝區。之後,將緩衝區內容寫入RequestStream,並採取進一步的操作(更新進度條等)。
編輯2:這似乎與LOH有關。我會在星期五進行測試,然後在這裏記錄結果。
編輯:這是代碼,也許我錯過了一個參考?
internal void ThreadRun(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
UploadItem current = Upload.GetCurrent();
if (current != null)
{
string localFilePath = current.src;
string fileName = Path.GetFileName(localFilePath);
elapsed = 0;
progress = 0;
try
{
string keyString = Util.GetRandomString(8);
worker.ReportProgress(0, new UploadState(0, 0, 0));
FtpWebRequest req0 = Util.CreateFtpsRequest("ftp://" + m.textBox1.Text + "/" + keyString, m.textBox2.Text, m.textBox3.Text, WebRequestMethods.Ftp.MakeDirectory);
req0.GetResponse();
FtpWebRequest req1 = Util.CreateFtpsRequest("ftp://" + m.textBox1.Text + "/" + keyString + "/" + fileName, m.textBox2.Text, m.textBox3.Text, WebRequestMethods.Ftp.UploadFile);
worker.ReportProgress(0, new UploadState(1, 0, 0));
byte[] contents = File.ReadAllBytes(localFilePath);
worker.ReportProgress(0, new UploadState(2, 0, 0));
req1.ContentLength = contents.Length;
Stream reqStream = req1.GetRequestStream();
Stopwatch timer = new Stopwatch();
timer.Start();
if (contents.Length > 100000)
{
int hundredth = contents.Length/100;
for (int i = 0; i < 100; i++)
{
worker.ReportProgress(i, new UploadState(3, i * hundredth, timer.ElapsedMilliseconds));
reqStream.Write(contents, i * hundredth, i < 99 ? hundredth : contents.Length - (99 * hundredth));
}
}
else
{
reqStream.Write(contents, 0, contents.Length);
worker.ReportProgress(99, new UploadState(3, contents.Length, timer.ElapsedMilliseconds));
}
int contSize = contents.Length;
contents = null;
reqStream.Close();
FtpWebResponse resp = (FtpWebResponse)req1.GetResponse();
reqStream.Dispose();
if (resp.StatusCode == FtpStatusCode.ClosingData)
{
FtpWebRequest req2 = Util.CreateFtpsRequest("ftp://" + m.textBox1.Text + "/storedfiles.sfl", m.textBox2.Text, m.textBox3.Text, WebRequestMethods.Ftp.AppendFile);
DateTime now = DateTime.Now;
byte[] data = Encoding.Unicode.GetBytes(keyString + "/" + fileName + "/" + Util.BytesToText(contSize) + "/" + now.Day + "-" + now.Month + "-" + now.Year + " " + now.Hour + ":" + (now.Minute < 10 ? "0" : "") + now.Minute + "\n");
req2.ContentLength = data.Length;
Stream stream2 = req2.GetRequestStream();
stream2.Write(data, 0, data.Length);
stream2.Close();
data = null;
req2.GetResponse().Dispose();
stream2.Dispose();
worker.ReportProgress(100, new UploadState(4, 0, 0));
e.Result = new UploadResult("Upload successful!", "A link to your file has been copied to the clipboard.", 5000, ("http://" + m.textBox1.Text + "/u/" + m.textBox2.Text + "/" + keyString + "/" + fileName).Replace(" ", "%20"));
}
else
{
e.Result = new UploadResult("Error", "An unknown error occurred: " + resp.StatusCode, 5000, "");
}
}
catch (Exception ex)
{
e.Result = new UploadResult("Connection failed", "Cannot connect. Maybe your credentials are wrong, your account has been suspended or the server is offline.", 5000, "");
Console.WriteLine(ex.StackTrace);
}
}
}
你怎麼知道的字節數組還活着的記憶是什麼? – BrokenGlass
你必須有一個你沒有擦除的內存的引用。您不必擦除字節數組的內容,必須刪除對它的所有引用,並且GC將重新使用該內存。 –
一些相關的代碼可能會有所幫助。有可能你正在做一些讓GC更難回收內存的問題(比如在某處保留引用)。 –