none
CImage的多线程使用问题 RRS feed

  • 问题

  • 关键点在于CImage中使用了静态成员:

    static CDCCache s_cache;

    CImage的GetDC调用了s_cache的GetDC,s_cache的GetDC如下:

    inline HDC CImage::CDCCache::GetDC() throw()
    {
    	HDC hDC;
    
    	for( int iDC = 0; iDC < CIMAGE_DC_CACHE_SIZE; iDC++ )
    	{
    		hDC = static_cast< HDC >( InterlockedExchangePointer( reinterpret_cast< void** >(&m_ahDCs[iDC]), NULL ) );
    		if( hDC != NULL )
    		{
    			return( hDC );
    		}
    	}
    
    	hDC = ::CreateCompatibleDC( NULL );
    
    	return( hDC );
    }

    即,当有缓存的HDC时,并没有直接创建而是返回上一次创建并且被Release的HDC。ReleaseDC如下:

    inline void CImage::CDCCache::ReleaseDC(_In_ HDC hDC) throw()
    {
    	for( int iDC = 0; iDC < CIMAGE_DC_CACHE_SIZE; iDC++ )
    	{
    		HDC hOldDC;
    
    		hOldDC = static_cast< HDC >( InterlockedExchangePointer( reinterpret_cast< void** >(&m_ahDCs[iDC]), hDC ) );
    		if( hOldDC == NULL )
    		{
    			return;
    		}
    		else
    		{
    			hDC = hOldDC;
    		}
    	}
    	if( hDC != NULL )
    	{
    		::DeleteDC( hDC );
    	}
    }

    当多个线程中使用CImage这个类时,就可能出现一个线程创建出来的HDC在Release之后,被缓存到m_ahDCs,而另外一个线程中再GetDC时可能就取到这个HDC了。

    在MSDN关于

    HDC CreateCompatibleDC(
      _In_  HDC hdc
    );

    有这样的说明:

    If hdc is NULL, the thread that calls CreateCompatibleDC owns the HDC that is created. When this thread is destroyed, the HDC is no longer valid. Thus, if you create the HDC and pass it to another thread, then exit the first thread, the second thread will not be able to use the HDC.

    但是在CImage中并没有提到关于多线程使用要注意的问题,我想请教一下CImage是否因此无法适用于多线程环境?

    2014年6月8日 5:55

全部回复