Avatar of alexatsearidge
alexatsearidgeFlag for Canada

asked on 

Occasional BitBlt failure, GetLastError=0

I'm seeing a very similar problem with my BitBlt's. It will return FALSE only occasionally (once every few hours, being called a few times a second) and an immediate call to GetLastError returns 0.

MFC in VS .NET 2003. I don't know what Hyperthreading is or whether I have it enabled, though.

We have a dialog app that connects over TCP/IP to a server and receives video data. On the data receive callback, we BitBlt the image into a CDC that was created in initialization using the following:

            CDC* clientDC = this->GetWindowDC();
            if(clientDC == NULL)
                  throw -1;

            if(! m_imageMemDC.CreateCompatibleDC(clientDC) )
                  throw -1;

            if(! m_imageMemBitmap.CreateCompatibleBitmap(clientDC, CAM_W*m_numCamW, CAM_H*m_numCamH))
                  throw -1;

            if( (m_pImageMemOldBitmap = m_imageMemDC.SelectObject(&m_imageMemBitmap)) == NULL )
                  throw -1;

            this->ReleaseDC(clientDC);

A Timer control is used to send a WM_PAINT every second. OnPaint, we StretchBlt the m_imageMemDC to the screen, as follows:

      CDC* clientDC = this->GetWindowDC();
      if(clientDC == NULL)
            return;

      clientDC->SetStretchBltMode(COLORONCOLOR);

      EnterCriticalSection(&m_imageMemDCSection);
      clientDC->StretchBlt(0, 0, clientWidth, clientHeight, &m_imageMemDC, 0, 0, CAM_W*m_numCamW, CAM_H*m_numCamH, SRCCOPY)
      LeaveCriticalSection(&m_imageMemDCSection);

      this->ReleaseDC(clientDC);

As you can see, we use a CCriticalSection, and lock it every time we access m_imageMemDC. Here's the BitBlt code:

            EnterCriticalSection(&m_imageMemDCSection);
            if(! ::BitBlt(m_imageMemDC.GetSafeHdc(), posX, posY + GetInfoBarHeight(), width-2, height - GetInfoBarHeight() *2,imgPtr->GetDC(), 0, 0, SRCCOPY))
                {
                  CString info;
                  info.FormatMessage(IDS_E_BITBLT, _camID,  GetLastError());
                  theLog.Log(info, EVENTLOG_ERROR_TYPE, 0, 0, CRITICAL);
                  TRACE (info);
            }
            LeaveCriticalSection(&m_imageMemDCSection);

As previously mentioned, we get the eventlog error, which includes the GetLastError() return code as '0', on average once an hour, but not at a regular interval.

Why does BitBlt fail?

Thanks.
System ProgrammingMultimedia ProgrammingC++

Avatar of undefined
Last Comment
Kent Olsen
ASKER CERTIFIED SOLUTION
Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Avatar of alexatsearidge

ASKER

Thanks!

Yes, I appreciate too that this is likely a design issue. I can provide other sections of code to test theories, but not my entire application...

I know that it is a best practice to keep critical section (ie. locked) code to a minimum, but I don't see how it could cause an error, in this example, with another function call that requires access to the same lock.

Also, I'm not sure I understand how to synchronize my "handling of that object ... to the main thread". I think that I'm already doing it using the Critical Section. I can't BitBlt when I'm StretchBlt'ing and vice versa.

You're certainly right about our performing a lot of processing in critical sections. I should add that we actually lock twice in OnDraw, the first time to do some drawing of text and rectangles on the DC, and then the second for the StretchBlt.  The only other times we lock are for the BitBlt on the socket thread, and in initialization when we set up the DC.
Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image

The only reason to lock objects using the EnterCriticalSection method is that the objects may be accessed by multiple threads.  (By definition, a single thread is nothing but a serial process so it can not interfere with itself.)

All of the GUI objects are controlled by the main thread.  If the main thread is locked, funny things happen with the Window Message Queue since the thread (application) isn't accessing the queue.  If the delay is long enough, multiple messages of the same type (timer tick, Click Event, etc.) may get queued.  When the application delay clears, all of the messages are processed en masse.  The application logic may not be able to handle the messages that fast so that it appears that events are missed.

Instead of performing complex formatting in a critical section, create two buffers and switch between the buffers in the critical section.  (Key variables will have to be declared as *volatile*.)

Kent

//
  ObjectType *Objects[2], 
             *ReadObject, 
             *WriteObject;
  ObjectIndex = 0;
//
//  Toggle the read/write objects
//
  EnterCriticalSection(...);
  ObjectIndex ^= 1;
  ReadObject = Objects[ObjectIndex];
  WriteObject = Objects[ObjectIndex ^ 1];
  LeaveCriticalSection (...);
//

Open in new window

Avatar of alexatsearidge

ASKER

OK, well after presenting information to management and getting their take on it, we've decided to redesign it a little bit.

We've simply taken the BitBlt out of the one thread, and are now sharing raw bitmaps between the threads. The main thread now does both the BitBlt'ing and the StretchBlt'ing (well it stretches the raw bitmaps onto a memory DC on a tick, and then on paint, it bitblt()s the memory dc onto the screen dc).

It looks like this re-threading cleared up the BitBlt() errors. Thanks for your help Kent (Kdo).
Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image


Great!

Glad that this did the trick.


Kent
C++
C++

C++ is an intermediate-level general-purpose programming language, not to be confused with C or C#. It was developed as a set of extensions to the C programming language to improve type-safety and add support for automatic resource management, object-orientation, generic programming, and exception handling, among other features.

58K
Questions
--
Followers
--
Top Experts
Get a personalized solution from industry experts
Ask the experts
Read over 600 more reviews

TRUSTED BY

IBM logoIntel logoMicrosoft logoUbisoft logoSAP logo
Qualcomm logoCitrix Systems logoWorkday logoErnst & Young logo
High performer badgeUsers love us badge
LinkedIn logoFacebook logoX logoInstagram logoTikTok logoYouTube logo