【发布时间】: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
到目前为止,我考虑了两个可能的问题并做了一些测试:
- TextBox 上删除第一行的方式不合适。
- 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