开发者

File.ReadAllText leading to memory leak [duplicate]

开发者 https://www.devze.com 2023-04-05 16:04 出处:网络
This question already has answers here: Closed 11 years ago. Possible Duplicate: TextBox.Text Leaking Memory in WPF Application
This question already has answers here: Closed 11 years ago.

Possible Duplicate:

TextBox.Text Leaking Memory in WPF Application

I've got an application trailing a logfile. Every time the logfile updates (which is usually a series of updates in a row) the memory use balloons out of control.

I've tracked down the problem to this call:

    if (File.Exists(Path + "\\logfile.txt"))
                Data = File.ReadAllText(Path + "\\logfile.txt");

This is being called from within LoadAllData, here.

    private void FileChangeNotificationHandler(object source, FileSystemEventArgs e)
    {
        this.Dispatcher.BeginInvoke
          (new Action(delegate()
          {
              Logfile.GetPath();
              Logfi开发者_JAVA百科le.LoadAllData();

              LogText.Clear();
              LogText.Text = Logfile.Data;
              if (CheckFollowTail.IsChecked == true) LogText.ScrollToEnd();
          }));
    }

Does anyone have insight on why this occurring? I assume it's related to the delegate or the handler.


It's probably just down to the amount and frequency with which you are loading log file data into memory.

GC takes time, so it you are repeating this in quick succession, then chances are you'll have several files worth of data in memory until the next GC. This seems very inefficient. You should consider the use of a stream based reader, to avoid keeping all the data in memory. If you do use a stream reader, make sure you dispose of it afterwards to avoid introducing another leak.

The another thing to check it that your not subscribing to a static event somewhere and therefore preventing your object tree from being disposed. Is it a web app?


First of all, checking if the file exists is wrong. This is because the file system is volatile and because there is more than just existence at play (permissions, for example). The correct way to do this is to just open the file, and then handle the exception if it fails.

Now, on to your stated problem. What I suspect is happening is that the log is growing large enough to use the Large Object Heap (85000 bytes is all that's needed, iirc, and remember that .Net uses utf16 (2-byte) characters). A 43K ascii log file is all you'll need to start causing problems, because at that size your .Net string is no longer garbage collected in the normal way. Every time you read the file you end up adding another instance of the entire log file to memory.

To best recommend how to get around this, it will be helpful to know what kind of component you use for your LogText variable. But pending that information, I can at least suggest a few pointers:

Ideally, you would just keep the file open (using FileShare.ReadWrite) and read from the stream every time you get a change notification. But that's not always possible.

If you have to re-open the file each time, at least read the text line by line (using a StreamReader) rather than pulling it all at once using File.ReadAllLines(). This will help you keep your log file broken up into smaller pieces that won't end up on the large object heap.

Unfortunately, I suspect that in the end you're stuck building one big string to assign to a plain textbox. If this is the case, I strongly recommend that you either only ever build and show the last part of the log (less than 85000 bytes worth) or that you search for a Large Object Heap-safe Textbox component to use.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号