如何恢复程序的内存使用量?

时间:2012-01-31 08:33:03

标签: c# winforms memory backgroundworker

我正在创建使用非常大量内存的应用。当我完成计算时,程序仍保持高内存,我在任务管理器中会注意到。

如何重置程序的RAM内存使用情况?

我正在创建一个大型数组,其中存储了MB值随机字符。然后将所有字符打印到变量中,然后将变量的内容写入文件。

namespace Fake_File_Creator
{
    public partial class MainWindow : Form
    {
        private string text;
        private List<char> stringChars;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnNewFile_Click(object sender, EventArgs e)
        {
            sfdNewFile.Filter = "All Files|*.*";

            if (sfdNewFile.ShowDialog() == DialogResult.OK)
            {
                lblMessage.Text = "Generating data...";
                bwCreateData.RunWorkerAsync((int)nudSize.Value * 1024000);
            }
        }

        private void bwCreateData_DoWork(object sender, DoWorkEventArgs e)
        {
            var random = new Random();
            var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 ~!@#$%^&*()_+ /.,'[];{}|:<>?";

            stringChars = new List<char>();

            for (int i = 0; i < (int)e.Argument; i++)
            {
                stringChars.Add(chars[random.Next(chars.Length)]);
            }

            text = new string(stringChars.ToArray());
        }

        void bwCreateData_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            lblMessage.Text = "Saving file...";
            bwCreateFile.RunWorkerAsync();
        }

        private void bwCreateFile_DoWork(object sender, DoWorkEventArgs e)
        {
            using (StreamWriter outfile = new StreamWriter(sfdNewFile.FileName))
            {
                outfile.Write(text);
            }
        }

        void bwCreateFile_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            lblMessage.Text = "File succesfully created...";
            text = string.Empty;
            stringChars.Clear();
            stringChars.TrimExcess();
        }
    }
}

4 个答案:

答案 0 :(得分:4)

你几乎无能为力。垃圾收集发生时,未使用对象占用的内存将被释放。而你不能强制垃圾收集。您可以在MSDN上阅读更多相关信息,同时查看GC Class

来自MSDN的示例

private const long maxGarbage = 1000;

static void Main()
{
    MyGCCollectClass myGCCol = new MyGCCollectClass();

    // Determine the maximum number of generations the system
    // garbage collector currently supports.
    Console.WriteLine("The highest generation is {0}", GC.MaxGeneration);

    myGCCol.MakeSomeGarbage();

    // Determine which generation myGCCol object is stored in.
    Console.WriteLine("Generation: {0}", GC.GetGeneration(myGCCol));

    // Determine the best available approximation of the number 
    // of bytes currently allocated in managed memory.
    Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));

    // Perform a collection of generation 0 only.
    GC.Collect(0);

    // Determine which generation myGCCol object is stored in.
    Console.WriteLine("Generation: {0}", GC.GetGeneration(myGCCol));

    Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));

    // Perform a collection of all generations up to and including 2.
    GC.Collect(2);

    // Determine which generation myGCCol object is stored in.
    Console.WriteLine("Generation: {0}", GC.GetGeneration(myGCCol));
    Console.WriteLine("Total Memory: {0}", GC.GetTotalMemory(false));
    Console.Read();
}

void MakeSomeGarbage()
{
    Version vt;
    for(int i = 0; i < maxGarbage; i++)
    {
       // Create objects and release them to fill up memory
       // with unused objects.
       vt = new Version();
    }
}

答案 1 :(得分:1)

具有资源的类型应该实现IDisposable,并且通过调用Dispose(或将它们包装在using语句中)来释放这些资源。 GC.Collect仅对具有资源但未实现IDisposable的对象是必需的。

答案 2 :(得分:1)

你不能强迫GC

但是如果你想在完成阵列后立即释放内存。

//I assume stringChars is the array
stringChars.Clear();
stringChars = null; 
GC.Collect(); 

答案 3 :(得分:0)

这取决于您要释放的内存类型。 真正调用GC.Collect();可能行不通。为什么呢?

  1. 它收集对象,但您不知道哪些对象。你的对象很大。通常,垃圾收集器不会收集大型物体,也不会很少(但很少用于机器时间测量而不是人类)。

  2. 为您的阵列分配的虚拟内存很可能不会释放到操作系统。因为虚拟机内存管理器通常重用已释放的内存。 他们还执行内存的预分配。他们分配大块内存然后使用它。它允许不执行大量系统调用来获取新对象的内存,因为.NET语言通常会创建大量的内容(与.NET内存管理器相比,C ++复制使用了很多,而堆是“虚拟”)。 / p>