3
votes

I have a MFC document/view C++ graphics application that does all its drawing to an off screen bitmap, and then copys that to the supplied CDC pointer in the OnDraw method. Over the last couple of days I've been looking to place the drawing component in a seperate worker thread, so it doesn't stall the GUI. I seem to get a fair number of MFC GDI related asserts firing when I do this, e,g,

VERIFY(::MoveToEx(m_hAttribDC, x, y, &point)

So a few questions;

  • Are there any problems with using worker threads with MFC & GDI?
  • Are there issues using MFC GDI objects across threads?
  • Do GDI objects have to be declared locally to a thread?

While it is possible the issue is resource/locking related, the drawing thread has its own provate CDC and CBitmap that it uses for all the drawing, and only copies the bitmap back to the main thread when it hasz excludive access via a mutex. The code has also been tested by direct calling rather than as a seperate thread to prove the problem does relate to threading.

2

2 Answers

2
votes

Device contexts can be used by any thread (the only thing you must be aware of is that the thread which did the GetDC should also call ReleaseDC), but are not inherently thread safe. You have to ensure that only one caller is accessing the DC at any given point in time, but you seem to have taken care of that, from what you write.

What do you mean by Do GDI thread have to be declared locally to a thread ? They must be allocated and freed in the same thread, but they can be created/used in any thread. Once again, you are responsible not to use such a resource from two threads simultaneously.

You should probably check the series of posts from Raymond Chen on the subject:

and be sure that you don't link to the single threaded versions of the C/MFC libraries.

1
votes

Raymond Chen has posted about this on his blog:

http://blogs.msdn.com/oldnewthing/archive/2005/10/11/479587.aspx

(There are other blog posts about thread affinity of windows objects which might be helpful to you).

Apparently for DCs you need to do the Get/Release on the same thread.

Hope that helps!