Я использую рабочий поток для накачки сообщений и использую обработчик событий в потоке пользовательского интерфейса, чтобы вызвать Control.Invoke, чтобы показать их в RichTextBox. Теперь он обнаружил, что генерирует исключение через 12 часов непрерывной работы на целевой машине.OutOfMemory Exception, когда Control.invoke
Вход показал, что:
System.OutOfMemoryException когда System.Windows.Forms.Control.MarshaledInvoke (вызывающий управления, метод делегата, Object [] арг, Boolean синхронные)
И вот часть моих кодов в Main Form:
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 точно.
Из-за идей, есть ли другая проблема, которую я пропустил?