2015-12-25 5 views
0

Я использую рабочий поток для накачки сообщений и использую обработчик событий в потоке пользовательского интерфейса, чтобы вызвать 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 

До сих пор я не рассмотрел два возможных проблем и сделал несколько тестов:

  1. Способ удаления первой строки в TextBox не подходит.
  2. Есть некоторые побочные эффекты о Control.Invoke, которые я не знаю прежде.

Для первого, я попытался поднять событие сообщения один раз на 1 мс на моем ноутбуке, после 24 часов тестирования он по-прежнему работает, без исключения.

По второй причине я прочитал How to avoid leaking handles when invoking in UI from System.Threading.Timer? и использую perfmon.exe для контроля за утечками дескриптора, кажется, что работает до сих пор, неиспользуемые ручки были собраны GC точно.

Из-за идей, есть ли другая проблема, которую я пропустил?

ответ

0

Нашел дефект на этой команде:

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

Если есть многострочное сообщение, приходящее с помощью аргумента электронной, было бы удалить только с самого началом одну строки за событие поднятой, так что использование кучи RichTextBox может продолжать расти в этой ситуации, конечно, в конце концов может произойти OutOfMemory.

В this post найден полезный альтернативный вызов, чтобы фиксировать линии на RichTextBox, он может решить эту проблему.

RichTextBoxHistory.Lines = RichTextBoxHistory.Lines.Skip(RichTextBoxHistory.Lines.Length - 64).ToArray() 
Смежные вопросы