TextBox.Text Утечка памяти в приложении WPF - PullRequest
3 голосов
/ 26 июля 2010

У меня есть приложение, которое обрабатывает большое количество чисел на массиве чисел.Я установил каждые 100 000 операций для отображения статуса этих номеров.Это всего лишь своего рода визуальный индикатор для оператора о том, что приложение все еще обрабатывает, и насколько близко оно к завершению.

После запуска приложения в течение нескольких часов происходит сбой с OutOfMemoryExeption.Я запустил CLRProfiler и обнаружил, что утечка происходит в TextBox, который показывает текущее состояние массива ... приложение строит ~ 4K в Char [] каждый раз, когда обновляется интерфейс, трассировка стека для каждого зависшего битапамять такая же.

Это ошибка в WPF или есть что-то, чего я не знаю, что мне следует делать, чтобы этого не происходило?Я не видел никаких других ссылок на это.Так как в любом случае это довольно трудоемкая операция, я бы предпочел не уничтожать и не перестраивать TextBox, если мне не нужно просто отображать текущее состояние массива.

Это единственныйутечка памяти, которую я могу найти, но из-за большого количества требуемых операций это на самом деле большая проблема для приложения, даже если я просто уменьшу частоту обновления интерфейса.Если вам нужна дополнительная информация, я помогу, если это вообще возможно, но, пожалуйста, поймите, что из-за того, что делает это приложение, я не могу публиковать практически любой исходный код, и мне придется что-либо анонимизировать (удаляя любые указанияцель приложения), которую я МОГУ опубликовать.

При запуске через CLR Profiler, который DRASTICALLY снижает производительность, следующая идентичная трассировка происходит каждые 2 секунды (помните: 100 000 операций), и память никогда не освобождается.Когда он работает без подключенного профилировщика, время между обновлениями составляет <1 секунду. </p>

Трассировка от одного обновления («Кто выделен»):

<root> :  3.7 kB    (100.00%)
 WpfApplication0.App::Main static void ():  3.7 kB    (100.00%)
  System.Windows.Application::Run int32 ():  3.7 kB    (100.00%)
   System.Windows.Application::Run int32 (System.Windows.Window):  3.7 kB    (100.00%)
    System.Windows.Application::RunInternal int32 (System.Windows.Window):  3.7 kB    (100.00%)
     System.Windows.Application::RunDispatcher Object (Object):  3.7 kB    (100.00%)
      System.Windows.Threading.Dispatcher::Run static void ():  3.7 kB    (100.00%)
       System.Windows.Threading.Dispatcher::PushFrame static void (System.Windows.Threading.DispatcherFrame):  3.7 kB    (100.00%)
        System.Windows.Threading.Dispatcher::PushFrameImpl void (System.Windows.Threading.DispatcherFrame):  3.7 kB    (100.00%)
         NATIVE FUNCTION ( UNKNOWN ARGUMENTS ):  3.7 kB    (100.00%)
          MS.Win32.HwndSubclass::SubclassWndProc int_ptr (int_ptr int32 int_ptr int_ptr):  3.7 kB    (100.00%)
           System.Windows.Threading.Dispatcher::Invoke Object (System.Windows.Threading.DispatcherPriority  Object):  3.7 kB    (100.00%)
            System.Windows.Threading.Dispatcher::InvokeImpl Object (System.Windows.Threading.DispatcherPriority   Object bool):  3.7 kB    (100.00%)
             System.Windows.Threading.Dispatcher::WrappedInvoke Object ( Object bool ):  3.7 kB    (100.00%)
              System.Windows.Threading.ExceptionWrapper::TryCatchWhen Object (Object  Object bool ):  3.7 kB    (100.00%)
               System.Windows.Threading.ExceptionWrapper::InternalRealCall Object ( Object bool):  3.7 kB    (100.00%)
                MS.Win32.HwndSubclass::DispatcherCallbackOperation Object (Object):  3.7 kB    (100.00%)
                 MS.Win32.HwndWrapper::WndProc int_ptr (int_ptr int32 int_ptr int_ptr bool&):  3.7 kB    (100.00%)
                  System.Windows.Threading.Dispatcher::WndProcHook int_ptr (int_ptr int32 int_ptr int_ptr bool&):  3.7 kB    (100.00%)
                   System.Windows.Threading.Dispatcher::ProcessQueue void ():  3.7 kB    (100.00%)
                    System.Windows.Threading.DispatcherOperation::Invoke Object ():  3.7 kB    (100.00%)
                     System.Threading.ExecutionContext::Run static void (System.Threading.ExecutionContext System.Threading.ContextCallback Object):  3.7 kB    (100.00%)
                      System.Threading.ExecutionContext::RunInternal static void (System.Threading.ExecutionContext System.Threading.ContextCallback Object):  3.7 kB    (100.00%)
                       System.Threading.ExecutionContext::runTryCode static void (Object):  3.7 kB    (100.00%)
                        System.Windows.Threading.DispatcherOperation::InvokeInSecurityContext static void (Object):  3.7 kB    (100.00%)
                         System.Windows.Threading.DispatcherOperation::InvokeImpl void ():  3.7 kB    (100.00%)
                          System.Windows.Threading.Dispatcher::WrappedInvoke(1) Object ( Object bool ):  3.7 kB    (100.00%)
                           System.Windows.Threading.ExceptionWrapper::TryCatchWhen(1) Object (Object  Object bool ):  3.7 kB    (100.00%)
                            System.Windows.Threading.ExceptionWrapper::InternalRealCall(1) Object ( Object bool):  3.7 kB    (100.00%)
                             System.Delegate::DynamicInvokeImpl Object (Object[]):  3.7 kB    (100.00%)
                              System.Reflection.RuntimeMethodInfo::Invoke Object (Object System.Reflection.BindingFlags System.Reflection.Binder Object[] System.Globalization.CultureInfo bool):  3.7 kB    (100.00%)
                               System.RuntimeMethodHandle::InvokeMethodFast Object (Object Object[] System.Signature System.Reflection.MethodAttributes System.RuntimeTypeHandle):  3.7 kB    (100.00%)
                                WpfApplication0.Window1::UpdateUI void ():  3.7 kB    (100.00%)
                                 System.Windows.Controls.TextBox::set_Text void (String):  3.7 kB    (100.00%)
                                  System.Windows.DependencyObject::SetValue void (System.Windows.DependencyProperty Object):  3.7 kB    (100.00%)
                                   System.Windows.DependencyObject::SetValueCommon void (System.Windows.DependencyProperty Object System.Windows.PropertyMetadata bool System.Windows.OperationType bool):  3.7 kB    (100.00%)
                                    System.Windows.DependencyObject::UpdateEffectiveValue System.Windows.UpdateResult (System.Windows.EntryIndex System.Windows.DependencyProperty System.Windows.PropertyMetadata System.Windows.EffectiveValueEntry System.Windows.EffectiveValueEntry& bool System.Windows.OperationType):  3.7 kB    (100.00%)
                                     System.Windows.DependencyObject::NotifyPropertyChange void (System.Windows.DependencyPropertyChangedEventArgs):  3.7 kB    (100.00%)
                                      System.Windows.Controls.TextBox::OnPropertyChanged void ():  3.7 kB    (100.00%)
                                       System.Windows.FrameworkElement::OnPropertyChanged void ():  3.7 kB    (100.00%)
                                        System.Windows.DependencyObject::OnPropertyChanged void (System.Windows.DependencyPropertyChangedEventArgs):  3.7 kB    (100.00%)
                                         System.Windows.Controls.TextBox::OnTextPropertyChanged static void ( ):  3.7 kB    (100.00%)
                                          System.Windows.Documents.TextContainer::DeleteContentInternal void (System.Windows.Documents.TextPointer System.Windows.Documents.TextPointer):  3.7 kB    (100.00%)
                                           System.Windows.Documents.TextTreeUndo::CreateDeleteContentUndoUnit static System.Windows.Documents.TextTreeDeleteContentUndoUnit (System.Windows.Documents.TextContainer System.Windows.Documents.TextPointer System.Windows.Documents.TextPointer):  3.7 kB    (100.00%)
                                            System.Windows.Documents.TextTreeDeleteContentUndoUnit::.ctor void (System.Windows.Documents.TextContainer System.Windows.Documents.TextPointer System.Windows.Documents.TextPointer):  3.7 kB    (100.00%)
                                             System.Windows.Documents.TextTreeDeleteContentUndoUnit::CopyContent ContentContainer (System.Windows.Documents.TextTreeNode System.Windows.Documents.TextTreeNode):  3.7 kB    (100.00%)
                                              System.Windows.Documents.TextTreeDeleteContentUndoUnit::CopyTextNode System.Windows.Documents.TextTreeNode (System.Windows.Documents.TextTreeTextNode System.Windows.Documents.TextTreeNode ContentContainer&):  3.7 kB    (100.00%)
                                               System.Char [] :  3.7 kB    (100.00%)

и код, генерирующийОбновление пользовательского интерфейса:

        List<int> arraystatus = new List<int>(displayarray.ToArray());

        StringBuilder s = new StringBuilder();

        int i = 1;

        foreach (int item in arraystatus)
        {
            s.Append(i.ToString() + ":\t" + item.ToString() + (i % 8 == 0 ? "\n" : "\t"));
            i++;
        }

        txtStatus.Text = s.ToString();

        arraystatus = null;
        s = null;

Ответы [ 2 ]

17 голосов
/ 26 июля 2010

Из документации свойства TextBoxBase.UndoLimit:

Количество действий, сохраненных в очереди отмены. Значение по умолчанию –1, что означает, что очередь отмены ограничена доступная память.

Вы нашли этот предел. Установите его на достаточно малое значение.

В противном случае обычно не имеет большого смысла отображать информацию журнала в TextBox. Это действительно означает, что пользователь может вводить текст. Возможно, TextBlock - лучший выбор.


ОБНОВЛЕНИЕ: в .NET 4.5 значение по умолчанию -1 было изменено на 100, чтобы избежать такого неконтролируемого использования памяти.

2 голосов
/ 26 июля 2010

+ 1 для Ганса.

Также вы используете StringBuilder.Удивительно.

Тем не менее, вы объединяете ЧЕТЫРЕ строки для каждого элемента в arraystatus (что может быть 100 КБ, насколько мне известно) при каждом обновлении вашего пользовательского интерфейса, что делает StringBuilder практически бессмысленным.

Попробуйте

s.Append(i.ToString());
s.Append(":\t");
s.Append(item.ToString());
s.Append(i % 8 == 0 ? "\n" : "\t"));

или, что еще лучше, попытайтесь преобразовать это в один вызов AppendFormat.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...