Re: Use a DC in a worker thread
On Sep 25, 3:54 pm, Joseph M. Newcomer <newco...@flounder.com> wrote:
See below....
On Wed, 24 Sep 2008 22:19:41 -0700 (PDT), Faisal <faisal...@gmail.com> wr=
ote:
On Sep 24, 8:35 pm, Joseph M. Newcomer <newco...@flounder.com> wrote:
Yes. There is actually an exmaple in the MSDN that does this.
The key here is to make sure that at no time do two threads have DCs t=
o the same window,
and that at no time do two threads try to manipulate the same DC.
You cannot do a progress bar only because StretchBlt does not give you=
progress
indications. BUT, if you broke the problem into a sequence of Stret=
chBlt calls (say the
image is 1024x1024; if you did StretchBlt of 128x128 pieces, you would=
have 64
opportunities to update the progress bar, one for each little piece yo=
u did. I don't have
any idea how good the output would look because I don't know how sensi=
tive StretchBlt is
to boundary conditions, but on the whole, you can assume that you are =
going to get crap.
Serious graphics requires doing decent image convolution algorithms th=
at will average
multiple pixels (there's a huge body of literature on this).
However, another solution is to simply StretchBlt into a memory DC and=
only handle the
resulting BLT to the client area DC in the main thread.
Does bliting to a memory DC and then to the device dc have any
performance advantage?
****
Sounds like you're asking "Is doing something twice faster than doing som=
ething once?" The
answer is obvious.
Generally, this technique is used not for performance reasons but to redu=
ce screen
flicker, which can be an important consideration.
****>In my case, I think the application takes the same time.
****
And how did you determine this? If the answer does not include the use=
of
QueryPerformanceCounter then you don't actually know.
joe
****
An advantage of the piecewise transformation (if it produces an accept=
able image) is that
you can actually display pieces at a time so the user doesn't just see=
a totally blank
screen. Problem is that you can't have a bitmap selected into two d=
ifferent DCs at the
same time, so you would have to be careful that you didn't need to do =
this to make it
work, whether the rendering was done to a memory DC or directly to the=
screen.
joe
On Wed, 24 Sep 2008 07:06:26 -0700 (PDT), Faisal <faisal...@gmail.com>=
wrote:
My application uses StretchBlt() to print some images and graphs.
Since StretchBlt () takes a few minutes to complete, user feels the
application is hanged.
As a solution I would like to move the StretchBlt () to a separate
thread. Is this a good solution? Can I manipulate a DC from a thread
other than its owner?
Also, I would like to show a progress bar while printing. How would I
know the steps once the StretchBlt()went to hang?
Joseph M. Newcomer [MVP]
email: newco...@flounder.com
Web:http://www.flounder.com
MVP Tips:http://www.flounder.com/mvp_tips.htm
Joseph M. Newcomer [MVP]
email: newco...@flounder.com
Web:http://www.flounder.com
MVP Tips:http://www.flounder.com/mvp_tips.htm
I didn't measure by time checking. I'm just giving my observation.
I thought this would increase the performance. So I asked that
question.
Now I modified the code to show a progress bar. For this I created a
UI thread before my long operation. In this thread I'm showing a
dialog with progress bar. And in between each small StrechBlt()
operation I tried to update the progress bar.
But, to my surprise dialog is not showing up, when i started the new
UI thread. Only when I'm returning from the current function in the
main thread, the dialog is showing. Is this an expected behavior?
While debugging it shows that the thread is starting up, but in the
dialog.create() call hangs and it returns only when the current
command procedure in main thread is returned. The exact function with
hangs is ::CreateDialogIndirect().
A stripped down version of my code is given below.
void CMainFrame::OnUIthrd()
{
CPBThread* pThread = new CPBThread();
pThread->CreateThread(CREATE_SUSPENDED)
pThread->ResumeThread();
for( int i = 0; i < 100; i++ )
{
Sleep( 100 ); // In real code I'm doing the stretch blit from here
pThread->m_nStep = i;
}
SetEvent( pThread->m_hEventKill );
}
Thread code is given here
BOOL CPBThread::InitInstance()
{
CProgessDlg* pProDlg = new CProgessDlg();
pProDlg->Create(IDD_PROGRSS, 0 );
pProDlg->ShowWindow(SW_SHOW);
// loop but check for kill notification
while (WaitForSingleObject(m_hEventKill, 0) == WAIT_TIMEOUT)
{
pProDlg->m_Progress.SetPos( m_nStep );
}
pProDlg->DestroyWindow();
delete pProDlg;
pProDlg = NULL;
// avoid entering standard message loop by returning FALSE
return FALSE;
}
I think there's some serious mistake in my understanding of UI thread.
How can I solve this problem?