2 votes

Je veux forcer un rendu, mais seulement dessiner aussi vite que possible (InvalidateVisual / CompositionTarget.Rendering)

Je travaille sur un composant de visualisation WPF/Silverlight (et bientôt WP7) en temps réel et je cherche la meilleure solution pour forcer un redessin de l'ensemble du composant dans un style Game-loop. Le redessin doit se faire à la demande, mais je ne veux pas sauvegarder la pompe à messages avec des appels de redessin. La plupart des dessins de mon composant sont réalisés à l'aide de primitives non-WPF (par exemple Bitmap Interop, Direct2D). Mon code n'utilise donc pas InvalidateVisual, et par conséquent, il ressemble actuellement à ceci

// Pseudocode, doesnt compile, just to convey the meaning
public void InvalidateElement()
{
    if (CurrentlyDrawing)
        return;

    Dispatcher.BeginInvoke(() => 
    {
        CurrentlyDrawing = true;

        DoDrawInternal();

        CurrentlyDrawing = false;            
    }
}

Ok, c'est génial. Si j'appelle InvalidateElement un grand nombre de fois, j'obtiens une bonne réactivité. Cependant, ce que je veux faire, c'est m'assurer que je peux envoyer des données à mon composant de visualisation aussi vite que possible, mais ne dessiner que lorsque le composant est capable de dessiner, et ne pas continuer à dessiner pour rattraper les données une fois que le flux d'entrée est terminé.

Non, je ne peux pas surcharger OnRender, j'utilise un dessin non-WPF dans WPF ;-)

En gros, ce que je veux, c'est quelque chose comme l'ancienne Invalidate() / OnPaint dans WindowsForms, ou mieux encore, une boucle de jeu dans DirectX.

Actuellement, si un thread externe envoie des données au composant de visualisation à un rythme élevé, si j'arrête d'envoyer des données, j'ai encore 20 secondes de rafraîchissement à passer avant que le composant ne cesse de s'afficher. Je veux arrêter de dessiner dès que les données sont entrées.

Une autre idée que j'ai eue était de gérer CompositionTarget.Rendering dans le composant de visualisation, puis d'implémenter une sorte de file d'attente rudimentaire pour y pousser les données et l'événement Rendering consomme ces données aussi vite qu'il le peut.

En résumé

Étant donné un composant de visualisation WPF, V, et une source de données D qui lui envoie des données toutes les 1ms, comment puis-je m'assurer que, quelle que soit la fréquence de données de D, V dessine des données à 30FPS (ou ce qu'il peut faire) et se met à jour par morceaux, un peu comme le fait une boucle de rendu de jeu dans DirectX ?

Lorsque les données s'arrêtent, V devrait redessiner tout ce qu'il a fait jusqu'à présent en une seule fois. Lorsque les données sont trop rapides, V dessine de plus gros morceaux à la fois pour compenser.

Si vous avez besoin de plus d'informations, je serai heureux de les partager. Pour l'instant, j'ai juste posté un synopsis pour voir s'il y a des solutions rapides, mais un Q plus complet avec des exemples de code peut être fourni sur demande.

Meilleures salutations,

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X