Question

Mon application de structure compacte crée une liste à défilement fluide en affichant tous les éléments sur une grande surface bitmap, puis en les copiant dans une position décalée à l'écran de manière à ce que seuls les éléments appropriés s'affichent. Les anciennes versions ne affichaient que les éléments devant apparaître à l'écran à ce moment-là, mais cette approche était trop lente pour une interface de défilement fluide.

Il génère parfois une exception OutOfMemoryException lors de la création initiale de la grande image bitmap. Si l'utilisateur effectue une réinitialisation logicielle du périphérique et exécute à nouveau l'application, il peut effectuer la création sans problème.

Il ne semble pas que cette image bitmap soit générée dans la mémoire de programme, car l'application utilise à peu près la même quantité de mémoire de programme qu'avant les nouvelles méthodes de défilement lisse.

Existe-t-il un moyen de prévenir cette exception? Est-il possible de libérer la mémoire dont j'ai besoin (où qu'elle se trouve) avant la levée de l'exception?

Était-ce utile?

La solution

Je suggérerais de revenir à l'ancien mécanisme consistant à ne restituer qu'une partie des données, car la taille des données intégralement rendues est évidemment un problème. Pour éviter les problèmes de rendu, je devrais probablement pré-afficher quelques lignes au-dessus et au-dessous de la vue actuelle afin de pouvoir les "faire défiler". avec un impact limité.

Autres conseils

Et dès que j'ai posté mon article, j'ai pensé à quelque chose que vous pouvez faire pour résoudre votre problème avec la nouvelle version. Le problème que vous avez, c’est que CF essaie de trouver un bloc de mémoire contiguë disponible pour l’immense bitmap, ce qui pose parfois un problème.

Au lieu de créer un gros bitmap, vous pouvez créer une collection de bitmaps plus petites, une pour chaque élément, et rendre chaque élément sur son propre petit bitmap. Pendant l’affichage, vous ne faites que copier les bitmaps dont vous avez besoin. Les FC auront beaucoup plus de facilité à créer un tas de petites images qu'un grand, et vous ne devriez pas avoir de problèmes de mémoire, à moins que ce ne soit une énorme quantité d'éléments.

Je devrais éviter les expressions telles que "il n'y a pas de solution".

Un autre point important: assurez-vous d'appeler Dispose () sur chaque bitmap lorsque vous avez terminé.

Votre bitmap est définitivement en train d'être créé dans la mémoire du programme. La quantité de mémoire dont a besoin le bitmap dépend de sa taille et du fait que cette taille requise générera ou non l'exception OutOfMemoryException dépend de la quantité disponible pour le PDA (ce qui en fait une erreur aléatoire).

Désolé, mais il s’agit généralement d’une technique de rendu de contrôle déconseillée (en particulier sur le Compact Framework) pour laquelle il n’existe pas de solution, à part augmenter la mémoire physique sur le PDA, ce qui n’est généralement pas possible (et souvent ne résout pas le problème). le problème de toute façon, puisqu’un processus CF est limité à 32 Mo, quel que soit le périphérique disponible).

Votre meilleur choix est de revenir à l'ancienne version et d'améliorer sa vitesse de rendu. CF propose également une technique simple permettant de créer une commande à double tampon afin d’éliminer le scintillement.

Puisqu'il semble que vous ayez rencontré une limitation de périphérique limitant la taille totale de l'espace Bitmap que vous pouvez créer (ceux-ci sont apparemment créés dans la RAM vidéo plutôt que dans la mémoire programme générale), une alternative consiste à remplacer le gros objet Bitmap. utilisé ici avec un bloc ancien de mémoire Windows, auquel il accède pour la lecture et l'écriture en invoquant la fonction API BitBlt.

La création initiale du bloc de mémoire est délicate et vous voudrez probablement poser une autre question à ce sujet (GCHandle.Alloc peut être utilisé ici pour créer un objet "épinglé", ce qui signifie que .NET n'est pas autorisé à déplacez-le en mémoire, ce qui est essentiel ici). Je sais comment le faire, mais je ne suis pas sûr de le faire correctement et je préférerais l'intervention d'un expert.

Une fois que vous avez créé le gros bloc, vous parcourez vos éléments, restituez chacun d'eux en un petit bitmap que vous continuez à réutiliser (en utilisant votre code .NET existant), et BitBlt à l'emplacement approprié de votre bloc mémoire.

Après avoir créé la totalité du cache, votre code de rendu devrait fonctionner comme avant, à la différence qu'au lieu de copier du gros bitmap sur votre surface de rendu, vous BitBlt à partir de votre bloc de cache. Les arguments de BitBlt sont essentiellement les mêmes que ceux de DrawImage (destination, source, coordonnées et tailles, etc.).

Puisque vous créez le cache à partir de la mémoire ordinaire de cette façon plutôt que de la mémoire vidéo spécialisée, je ne pense pas que vous rencontrerez le même problème. Cependant, je voudrais certainement que le code de création de bloc fonctionne d’abord et que je vérifie qu’il peut créer un bloc assez gros à chaque fois.

Mise à jour: en fait, l’idéal serait d’avoir une collection de plus petits blocs de mémoire plutôt qu’un gros (comme j’ai pensé que c’était le problème de l’approche Bitmap), mais vous en avez déjà assez. J'ai travaillé avec des applications CF qui traitent des objets de 5 et 10 Mo et ce n'est de toute façon pas un gros problème (bien que cela puisse être un problème plus important lorsque ce morceau est épinglé - je ne sais pas). Au fait, j'ai toujours été surpris par la création d'OOME sur BitMap car je savais que les bitmaps étaient beaucoup plus petites que la mémoire disponible, tout comme vous - je sais maintenant pourquoi. Désolé, je pensais que c'était une solution facile au début.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top