【问题标题】:OutOfMemory Exception when Control.invokeControl.invoke 时出现 OutOfMemory 异常
【发布时间】:2015-12-25 08:23:10
【问题描述】:

我使用工作线程来抽取消息,并使用 UI 线程上的事件处理程序来调用 Control.Invoke 以在 RichTextBox 上显示它们。 现在发现它会在目标机器上连续运行 12 小时后产生异常。

日志显示:

System.OutOfMemoryException 当 System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)

这是我在主窗体中的部分代码:

Dim __lastMessage As String = ""    
Private Sub historyMessageHandler(ByVal sender As messageHandler, ByVal e As String) Handles messengerReference.MessagePoped

    'prevent invoking after form closed
    If (Me.IsDisposed) Then
        Exit Sub
    End If

    Dim __thisMessage As String = e

    If (__lastMessage <> __thisMessage) Then
        '---------------------------
        ' Once this message is not equal to last mesage  , post on the history panel
        '---------------------------
        Me.Invoke(Sub()
                      RichTextBoxHistory.Text += (e & vbCrLf)
                      '-------------------------------------------
                      '    Discard oldest message if count reached to prevent buffer overload
                      '-------------------------------------------
                      If (RichTextBoxHistory.Lines.Length > 64) Then
                           RichTextBoxHistory.Text = String.Join(vbCrLf,RichTextBoxHistory.Lines, 1, RichTextBoxHistory.Lines.Count - 1)
                      End If
                      '----------------------
                      ' keep scoll on bottom
                      '---------------------
                  textBox.SelectionStart = textBox.Text.Length
                  textBox.ScrollToCaret()

                  End Sub)
    Else
        '-----------------------
        'redundant message found , no need to show
        '-----------------------

    End If

    __lastMessage = __thisMessage  'memorize last message
End Sub

到目前为止,我考虑了两个可能的问题并做了一些测试:

  1. TextBox 上删除第一行的方式不合适。
  2. Control.Invoke 有一些副作用,我以前不知道。

对于第一个,我尝试在我的笔记本电脑中每 1 毫秒触发一次消息事件,经过 24 小时测试,它仍然有效,无一例外。

出于第二个原因,我阅读了How to avoid leaking handles when invoking in UI from System.Threading.Timer?,并使用 perfmon.exe 来监控句柄是否泄漏,目前看来工作正常,GC 肯定会收集未使用的句柄。

现在没有想法了,还有其他我错过的问题吗?

【问题讨论】:

    标签: vb.net multithreading winforms memory-leaks


    【解决方案1】:

    发现此命令有缺陷:

    RichTextBoxHistory.Text =
    String.Join(vbCrLf,RichTextBoxHistory.Lines, 1,
    RichTextBoxHistory.Lines.Count - 1)
    

    如果有来自参数e的多行消息,它只会删除每个引发事件的最开始的单行,因此RichTextBox的堆使用量可能会在这种情况下不断增长,当然还有最后可能发生OutOfMemory

    this post,找到了有用的替代调用来保持RichTextBox上的固定行,它可以解决这个问题。

    RichTextBoxHistory.Lines = RichTextBoxHistory.Lines.Skip(RichTextBoxHistory.Lines.Length - 64).ToArray()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-12
      • 2015-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多