WPF 应用程序中的 TextBox.Text 内存泄漏 [英] TextBox.Text Leaking Memory in WPF Application

查看:14
本文介绍了WPF 应用程序中的 TextBox.Text 内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序可以对一组数字进行大量的数字运算.我将它设置为每 100,000 次操作以显示这些数字的状态.这对于操作员来说只是一种视觉指示,表明应用程序仍在处理中,以及距离完成还有多远.

I have an application that does a large amount of number crunching on an array of numbers. I have it set to every 100,000 operations to display the status of those numbers. This is just sort of a visual indicator to the operator that the application is still processing, and how close it is to completed.

在运行应用程序几个小时后,它因 OutOfMemoryExeption 崩溃.我在它上面运行了 CLRProfiler,发现泄漏发生在显示数组当前状态的 TextBox 中......每次接口更新时,应用程序在 Char[] 中构建~4K,每一个挂起的位的堆栈跟踪内存是一样的.

After running the application for several hours, it crashes with an OutOfMemoryExeption. I ran CLRProfiler on it, and found that the leak is occurring in the TextBox that shows the current state of the array... the application builds ~4K in Char[] every time the interface updates, the stack trace for each bit of hung memory is the same.

这是 WPF 中的错误,还是我不知道我应该做些什么来防止这种情况发生?我还没有看到任何其他对此的引用.无论如何,这是一个非常占用处理器的操作,如果我不必只显示数组的当前状态,我宁愿不必销毁和重建 TextBox.

Is this a bug in WPF, or is there something that I don't know I should be doing to prevent this from happening? I've not seen any other references to this. Since this is a pretty processor intensive operation anyway, I'd prefer not to have to destroy and rebuild the TextBox if I don't have to just to display the current state of the array.

这是我能找到的唯一内存泄漏,但由于需要的操作数量庞大,这对于应用程序来说实际上是一个大问题,即使我只是降低界面更新的频率.如果您需要更多信息,我会尽可能提供帮助,但请理解,由于此应用程序的作用,我几乎无法发布任何源代码,而且我必须匿名化任何内容(删除任何关于应用程序的目的),我可以发布.

This is the only memory leak that I can find, but due to the sheer number of operations required, it's actually a big problem for the application, even if I simply reduce the frequency of the interface update. If you need more information, I'll assist if at all possible, but please understand that due to what this application does, I can't post hardly any source code, and I'll have to anonymize anything (removing any indication of the application's purpose) that I CAN post.

当通过 CLR Profiler 运行时,这会显着降低性能,以下相同的跟踪每 2 秒发生一次(记住:100,000 次操作)并且永远不会释放内存.当它在没有附加分析器的情况下运行时,更新之间的时间是 <1 秒.

When run through the CLR Profiler, which DRASTICALLY reduces performance, the following identical trace occurs every 2 seconds (remember: 100,000 operations) and the memory is never deallocated. When it's running without a profiler attached, the time between updates is < 1 second.

来自一次更新(谁分配")的跟踪是:

The trace from one update ("Who Allocated") is:

<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%)

生成 UI 更新的代码是:

and the code generating a UI update is:

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

        StringBuilder s = new StringBuilder();

        int i = 1;

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

        txtStatus.Text = s.ToString();

        arraystatus = null;
        s = null;

推荐答案

来自 TextBoxBase.UndoLimit 属性的文档:

From the documentation of the TextBoxBase.UndoLimit property:

存储在撤消队列中的操作数.默认值为 –1,即意味着撤消队列仅限于可用内存.

The number of actions stored in the undo queue. The default is –1, which means the undo queue is limited to the memory that is available.

您找到了那个限制.将其设置为一个相当小的值.

You found that limit. Set it to a reasonably small value.

否则,在 TextBox 中显示日志信息通常没有多大意义.它实际上是为了允许用户输入文本.也许 TextBlock 是更好的选择.

It otherwise doesn't normally make a lot of sense to display logging information in a TextBox. It is really meant to allow the user to enter text. Perhaps TextBlock is a better choice.

更新:在 .NET 4.5 中,-1 的默认值更改为 100 以避免这种失控的内存使用.

UPDATE: in .NET 4.5, the default of -1 was changed to 100 to avoid this kind of runaway memory usage.

这篇关于WPF 应用程序中的 TextBox.Text 内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆