2010-08-12 7 views
0

Je rencontre actuellement des problèmes avec une application MVVM WPF. Dans l'application, le ViewModel est associé en tant que DataContext pour une vue à l'aide d'un DataTemplate dans un ResourceDictionary - de cette façon aucun des deux objets n'a de référence en code à l'autre. Mon ViewModel a une ressource non gérée qui doit être libérée lorsque mon ViewModel est parti. (Dans ce cas, ma ressource est une classe qui utilise une DLL externe)Fermer les ressources non managées lorsque l'application WPF est fermée

Si je n'utilise pas réellement la DLL, lorsque je ferme l'application, le finaliseur de ma ressource non managée est appelé, ce qui nettoie la DLL (J'implémente IDisposable). Tout est bon là-bas.

Si j'utilise la DLL, lorsque je ferme l'application, le finaliseur pour ma ressource n'est pas appelé et le processus ne se termine pas. Si je casse, je peux voir que la DLL bloque sur un appel à System.Net.Sockets.Socket.Receive(). Je suppose que ce qui se passe est que ma DLL survit à mon ViewModel, donc le ViewModel n'est jamais finalisé. D'après ce que j'ai lu, il est mauvais de s'appuyer sur un objet en cours de finalisation - vous ne pouvez pas faire confiance au GC. Alors, quelles options dois-je appeler CleanUp() sur ma ressource lorsque je veux fermer l'appplication - étant donné que View et ViewModel n'ont pas de références les uns aux autres?

Modifier: Pour une lecture supplémentaire, c'est le blog post à propos de Finalizers que je référençait.

Éditer 2: J'ai trouvé une solution qui me plaît assez, donc je me suis dit que je l'ajouterais pour la postérité et pseudo-ferment cette question. Au démarrage de l'application, j'initialise les View et ViewModel principaux pour mon application, donc c'est la source unique qui a une référence aux deux. J'ai attaché un EventHandler sur View.Closed qui déclenche une méthode CleanUp() sur mon ViewModel, qui est capable de propager cette logique dans toute l'application. Je maintiens MVVM et arrive à nettoyer les ressources offensantes sans trop de problèmes.

Répondre

1

Non, vous pouvez certainement faire confiance au GC. Vous ne pouvez pas approuver les DLL que vous n'avez pas écrites et qui démarrent des threads qui appellent Socket.Receive(). Vous devrez aborder cela en parlant au propriétaire du code DLL. Si vous avez créé le thread vous-même, définissez sa propriété IsBackground sur true.

+0

J'ai essayé d'invoquer l'appel DLL sur un thread où j'ai défini IsBackground sur true - mais j'avais toujours le même problème. J'espérais que si l'UI Dispatcher n'avait rien d'autre à faire, cela pourrait contraindre l'autre à s'arrêter. – bsg

+0

+1 pour définir IsBackground sur true (si vous possédez le thread). Vous pouvez * compter * dans le GC pour finaliser votre objet, mais vous * ne pouvez pas * compter sur le GC pour libérer des références à des objets pour vous. Si votre objet a des références à un autre objet non-disposé (les gestionnaires d'événements étant un grand) alors le GC ne supprimera pas votre objet. En substance, vous pouvez toujours avoir des fuites de mémoire avec .NET et consommer toute la mémoire disponible sur votre ordinateur, juste aucune qui échappe à votre AppDomain - donc quand votre application vous ferme * pouvez * faire confiance au GC pour libérer toute la mémoire associée à votre app. – Doug

Questions connexes