2009-05-27 7 views
0

J'ai écrit un petit programme interne en C# qui convertit en lots entre différents formats de fichiers, en s'appuyant principalement sur d'autres API. Actuellement, l'interface utilisateur génère un BackgroundWorker (pas un thread) pour gérer les conversions, puis remplit une file d'attente avec les demandes qui se vide lorsque le travailleur termine les tâches. Les objets de file d'attente eux-mêmes sont très petits (3 chaînes pour indiquer au travailleur quoi faire) et ne contribuent pas beaucoup à l'empreinte mémoire du programme. J'ai été assez draconien avec ma gestion de la mémoire (disposer des images quand elles sont terminées, et collecter manuellement les ordures à certains points.) Pourtant, le programme a tendance à utiliser environ 100 Mo de mémoire à la fois, et utilise environ 50% de temps total du processeur. Il semble que si j'utilisais naïvement le threading, il manquerait rapidement de mémoire système (à moins que le CLR ne fasse une sorte de magie que je ne connais pas.)Empêcher les applications multithread de manquer de mémoire

Y at-il un moyen simple/efficace de générer des threads pour éviter le système manque de mémoire en plus d'intercepter les exceptions OutOfMemory et de revenir sur le thread qui est mort (semble très inefficace, mais il n'y a aucun moyen de préserver l'état sans utiliser des quantités de mémoire prohibitives)?

+2

De combien de threads parlons-nous? Vous parlez de l'assurance-chômage et d'un travailleur ... mais cela ne devrait pas être un gros problème; Frayez-vous * beaucoup * de fils? –

+0

J'ai actuellement un objet BackgroundWorker (pas un Thread). Je voudrais ajouter plus pour permettre une plus grande utilisation de CPU mais empêcher le système de manquer de mémoire. Comme je l'ai dit, l'interface utilisateur avec un opérateur prend jusqu'à 100 Mo de RAM, donc même en ajoutant quelques threads supplémentaires pourrait être un problème. Les tâches par lot peuvent généralement contenir plus de 100 fichiers. – pschorf

Répondre

2

Si vous utilisez le ThreadPool.QueueUserWorkItem pour frayer les conversions que vous obtiendrez automatiquement une limite sur le nombre de threads qui sont en cours d'exécution. ThreadPool gère cela en interne et traite les appels en file d'attente dès qu'un thread de pool devient disponible.

0

Limitez la taille de la file d'attente et attendez que l'expéditeur soit saturé. Vous devriez cependant trouver la bonne limite de taille de la file d'attente de façon empirique.

0

Les exceptions de mémoire insuffisante peuvent être difficiles et peuvent être causées par une mémoire fragmentée, sans réellement manquer de mémoire. Par conséquent, ils peuvent être difficiles à traquer.

Tess du support produit Microsoft dans Sweeden (http://blogs.msdn.com/tess/) a un bon nombre de messages sur le suivi de la mémoire où la mémoire va aider à ce processus.

Un bon profil de votre application pourrait également aider. JetBrains en a un bon comme AQTime.

0

L'utilisation de 100 Mo de mémoire n'est pas importante pour une application de traitement d'image.

En outre, dans .net lorsque vous obtenez une exception OutOfMemory, le processus entier meurt, vous ne pouvez pas récupérer à partir de cela. Si vous avez besoin de plus de mémoire (ou, plus correctement, de plus d'espace d'adressage) que ce que le système peut vous donner, vous pouvez utiliser la mémoire de page et l'utiliser lorsque vous l'utilisez ou passer en 64 bits. Vous pouvez limiter la taille de la file d'attente pour vous assurer que le seul utilisateur "lourd" est le thread de travail, vous pouvez avoir plus d'un thread de travail, ce qui augmentera votre utilisation de la mémoire, mais videra la file plus rapidement que dans un CPU opérations intensives comme celle-ci ayant plus de threads que les cœurs de CPU est inefficace.

Vous parlez de "threading naïvement implémenté", le multi-threading est plein de pièges - une implémentation naïve sera inefficace et plein de bugs.

Questions connexes