J'ai une application qui effectue une grande quantité de calculs sur un tableau de nombres. Je l'ai mis à 100 000 opérations pour afficher le statut de ces chiffres. Ceci est juste une sorte d'indicateur visuel pour l'opérateur que l'application est encore en cours de traitement, et à quel point il est proche de l'achever. Après l'exécution de l'application pendant plusieurs heures, il se bloque avec une exception OutOfMemoryException. J'ai couru CLRProfiler sur lui, et a constaté que la fuite se produit dans le TextBox qui montre l'état actuel du tableau ... l'application construit ~ 4K dans Char [] chaque fois que l'interface met à jour, la trace de pile pour chaque morceau la mémoire est la même.TextBox.Text Fuite de mémoire dans l'application WPF
Est-ce un bug dans WPF, ou y a-t-il quelque chose que je ne sais pas que je devrais faire pour éviter que cela ne se produise? Je n'ai pas vu d'autres références à cela. Comme il s'agit quand même d'une opération assez gourmande en processeur, je préférerais ne pas avoir à détruire et à reconstruire le TextBox si je n'ai pas besoin de simplement afficher l'état actuel du tableau. C'est la seule fuite de mémoire que je peux trouver, mais en raison du nombre d'opérations nécessaires, c'est vraiment un gros problème pour l'application, même si je réduis simplement la fréquence de la mise à jour de l'interface. Si vous avez besoin de plus d'informations, je vous aiderai dans la mesure du possible, mais veuillez comprendre qu'en raison de ce que fait cette application, je ne peux pas publier de code source, et je vais devoir tout anonymiser (en supprimant toute indication l'application) que je peux poster. Lorsqu'il est exécuté à travers le profileur CLR, ce qui réduit drastiquement les performances, la trace identique suivante apparaît toutes les 2 secondes (rappelez-vous: 100 000 opérations) et la mémoire n'est jamais libérée. Lorsqu'il est exécuté sans profileur, l'intervalle entre les mises à jour est < 1 seconde.
La trace d'une mise à jour ("Qui affecté") est:
<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%)
et le code à générer une mise à jour de l'interface utilisateur est:
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;
Est-ce un bug dans WPF? 99% sûr non. Est-ce que vous allouer des craptons de chaînes? Pourrait être, pas sûr de votre code. Y a-t-il un meilleur moyen? Probablement. – Will
En outre, la mémoire n'est généralement pas libérée lors du débogage; est-ce que cela se produit pendant la diffusion? – Will
C'est littéralement le seul bit de code qui crée une chaîne après la création initiale de l'interface utilisateur. Il est encapsulé dans une méthode invoquée par le répartiteur depuis mon thread de travail toutes les 100 000 opérations. Oui, c'est beaucoup de ficelles. Ma question est "Pourquoi ne partent-ils pas?". Et oui, cela arrive dans la version ou le débogage. –