2017-02-03 4 views
-1

Mon application tire ses graphiques d'un thread de travail depuis plus de 10 ans et je n'ai jamais eu de problème avec celle-ci. Le thread de travail tire à mon HWND (créé par le thread principal) comme ceci:Dessiner une fenêtre à partir d'un fil d'enfant

hdc = GetDC(hwnd); 
SetDIBitsToDevice() ... or StretchDIBits() 
ReleaseDC(hwnd, hdc); 

Après avoir porté mon application à d'autres plates-formes, j'ai commencé à se rendre compte que le dessin d'un autre fil que le thread principal est habituellement un no-go sur de nombreuses plateformes (par exemple macOS). Ma recherche a montré que cela pourrait être vrai pour Win32, mais il me manque encore une réponse définitive.

Ainsi, ma question:

Est-il permis de tirer de ma fenêtre comme ci-dessus à partir d'un thread de travail qui n'a pas créer la fenêtre, il tire à? Notez que le thread de travail est vraiment le seul thread qui attire vers la fenêtre. Le thread principal ne fait aucun dessin. Pas même dans WM_PAINT. Dessin dans WM_PAINT est inutile dans mon cas, car le thread de travail dessine à 50fps.

Si ce n'est pas autorisé, quelle est la meilleure façon de déléguer le dessin du thread de travail au thread principal?

+0

http://stackoverflow.com/questions/5622850/hwnd-thread-affinity-painting-from-a-different-thread – VuVirt

+0

Ceci était définitivement faux sur Win32, et a toujours été. Si cela a fonctionné de manière fiable (et je suppose que ce n'était pas le cas, les bugs étaient difficiles à reproduire), c'était un accident. Tout le dessin doit être fait en réponse à 'WM_PAINT', point. Pourquoi une application aurait-elle besoin de tirer à 50 fps? S'il s'agit d'un jeu ou d'un autre type de commerce sophistiqué qui a besoin de 50 fps, vous devriez probablement utiliser DirectX ou autre. –

+0

Quoi qu'il en soit, si vous devez faire cela, répartissez-le sur plusieurs threads: demandez à votre thread de travail de préparer la section DIB, puis de forcer la fenêtre à se redessiner immédiatement en appelant le 'RedrawWindow'. Le thread principal recevra alors un message 'WM_PAINT', et à l'intérieur de ce gestionnaire de message, vous dessinez la section DIB dans le DC que vous recevez avec le message. Encore une fois, il n'est pas clair ce que l'utilisation de plusieurs threads vous achète ici, mais cela va le faire fonctionner. –

Répondre

1

Est-il autorisé à dessiner à ma fenêtre comme indiqué ci-dessus à partir d'un thread de travail qui n'a pas créé la fenêtre à laquelle il dessine?

Il ne peut pas être la meilleure solution à votre problème, mais il est sûr, tant que vous respectez les règles documentées pour GetDC:

  • Notez que la poignée à la DC ne peut être utilisé par un seul fil à la fois.
  • ReleaseDC doit être appelée à partir de la même unité d'exécution appelée GetDC.

Si vous rendez au même contexte de périphérique à partir de plusieurs threads, vous êtes responsable de la synchronisation des accès à elle. Comme expliqué dans les commentaires, une meilleure solution consisterait à générer la DIB à partir du thread de travail, et de mettre à jour cette fenêtre en appelant le RedrawWindow. Le thread principal peut alors StretchBlt dans son gestionnaire WM_PAINT. L'appel RedrawWindow à travers les threads implémente une barrière de synchronisation. Lorsque l'appel revient, le rendu sur le thread cible est terminé et il est possible de réutiliser le DIB en toute sécurité.


* Voir Thread affinity of user interface objects, part 2: Device contexts.