|
I have not used the GDI+ classes before, but do you need to have the delete &bp line, as this looks like your trying to delete a pointer to an object on the stack?
The only thing I would check in the documentation is that constructing a Bitmap will call the delevant HBITMAP desroy function in the ~Bitmap() function. It probably does that if the guys/gals who wrote the GDI+ library knew their stuff.
Roger Allen - Sonork 100.10016
If your dead and reading this, then you have no life!
|
|
|
|
|
What did images.Create(...) return?
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
public:
CImageList images;
BOOL m_i;
...
m_i=images.Create (IDB_SYMBOLS, 16, 0, RGB (192, 192, 192));
...
for(i=0;i<n;i++)
{
if(!m_i)="" break;="" but="" m_i="=TRUE
" hicon="" nicon;
="" nicon="images.ExtractIcon(0);
" if(!nicon)="" afxmessagebox("icon="" null");
="" bitmap="" bp(nicon);="" is="" gdi+="" class
="" graphics-="">DrawImage(&bp,(float)x1-8.0f,(float)y1-8.0f,16.0f,16.0f);
delete &bp;
DestroyIcon(nIcon);
}
//m_i==TRUE
Upwords code,memory leak out,all the same .why?
Thanks for your help!
VC/MFC fans.
|
|
|
|
|
There is no reason to check m_i each iteration through the for loop.
I suggest setting a breakpoint on the ExtractIcon() statement and step into it to see why it is returning NULL .
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
I'm writing a multi-threaded serial port program, that requires the implementation of a highly precise timer routine (around 3ms accuracy). To do this I create a worker thread which sleeps for 3ms (this is actually based upon the code from an article on windows timers from this site), processes a small amount of data and then posts a message on the windows message queue using PostMessage. The problem is when I do this I get an Access Violation.
All my related variables are stored on the heap and the handle I'm using is definately valid. I do a similar thing in each of the serial reader threads without any problem, so what am I doing wrong.
Now, I'm not brilliant at C++, particularly on a Windows platform, so please go easy on me, as it's probably something really obvious and stupid.
Here's a fragment of my timer code:
DWORD WINAPI TimerFunction(void* pParam)<br />
{<br />
CThreadTimer* obj = (CThreadTimer*) pParam;<br />
BOOLEAN isActive = TRUE;<br />
do<br />
{<br />
Sleep(obj->elapse);<br />
<br />
EnterCriticalSection(&obj->lock);<br />
isActive = obj->isActive;<br />
LeaveCriticalSection(&obj->lock);<br />
if(isActive){<br />
CTimerRoutines* ctr = (CTimerRoutines*) obj->object;<br />
if(ctr->TimerHandler())<br />
PostMessage(obj->ghMsgWnd, UM_TRIGEVENT, (WPARAM) NULL, (LPARAM) NULL);<br />
}<br />
} while ( isActive );<br />
<br />
return 0;<br />
}<br />
CTimerRoutines contains my data handling routines, but the problem lies somewhere in the PostMessage call.
Any help appreciated.
|
|
|
|
|
Solution is logically sound.
Add breakpoins before and after the call to PostMessage(). What causes the error?
Make sure the program passes in a valid handle to CTimerRoutines structure at the creation point of the thread. Post that code.
Kuphryn
|
|
|
|
|
I have inserted breakpoints in my code and can happily step through it without problem. Even the PostMessage command executes without incident right up to the point when the main thread (with the message queue) continues execution and then I get my Access Violation.
The thread setup code looks like this:
UINT CThreadTimer::SetTimer (void* obj, UINT nIDEvent, UINT uElapse, ThreadTimerProc lpTimerProc)<br />
{<br />
object = obj;<br />
idEvent = nIDEvent;<br />
elapse = uElapse;<br />
proc = lpTimerProc;<br />
<br />
EnterCriticalSection(&lock);<br />
if (isActive)<br />
{<br />
LeaveCriticalSection(&lock);<br />
return 0;<br />
}<br />
<br />
DWORD threadId; <br />
HANDLE threadHandle = CreateThread (NULL, 0, TimerFunction, this, 0, &threadId); <br />
SetThreadPriority(threadHandle,THREAD_PRIORITY_TIME_CRITICAL);<br />
isActive = TRUE;<br />
LeaveCriticalSection(&lock);<br />
return nIDEvent;<br />
}<br />
Note that the setup routine resides within a class called CThreadTimer, and a reference to this class is passed to the main thread routine. This hasn't caused me any problems before.
Any ideas?
|
|
|
|
|
One question... The Sleep() function is not from the Windows API, is it? Because there is no way you will 3ms with any accuracy with that. See this[^] for the reason.
John
|
|
|
|
|
John M. Drescher wrote:
The Sleep() function is not from the Windows API, is it?
It is part of the platform SDK.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
I know. My point is if he/she is using that one a 3ms delay is impossble.
John
|
|
|
|
|
The Sleep() function is from the Windows API and tends to be highly accurate particularly when runs from a thread operating at a Real-time priority level.
I have read the article you refer to and was also under that impression, but when I actually tested the system using this method with the HighPerformance counter function I found that the Sleep() function operated reliably down to 1ms and returned virtually immediately.
When I loaded the system down by performing a lot of highly computational programs, the accuracy deminished to 1.1ms - 0.1ms of delay was added due to system overhead.
(I am however running on a 2GHz Celeron system under XP Pro, maybe that's make a significant difference)
|
|
|
|
|
Thanks for the info. I have not tested this recently but with previous operating systems this information was correct. MS must have changed the implementation in XP.
John
|
|
|
|
|
PostMessage should not give you an access violation, no matter what parameters you pass so the problem must be with obj.
John
|
|
|
|
|
Hi Everyone,
I implemente a thread in a MFC application that can be started and stopped through 2 buttons. My problem: After i click the Stop button, the while-loop doesn't break, meaning that WaitForSingleObject does never return WAIT_OBJECT_0. How can i terminate a thread like this using wait for single object?
I noticed that some calls to PeekMessage inside the while loop make WaitForSingleObject return WAIT_OBJECT_0.
I really don't understand why this isn't working! Please can anybody help??
Jason
//-------------------------------------------------------------------------
void CAnyDlg::OnStart()
{
// declarations
DWORD dwId;
// start the thread
m_bThread=true;
if(m_hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)StartThread,(LPVOID)this,0,&dwId))
}
//-------------------------------------------------------------------------
void CAnyDlg::OnStop()
{
MSG msg;
while(::WaitForSingleObject(m_hThread,100)!=WAIT_OBJECT_0))
{
m_bThread=false;
}
}
//-------------------------------------------------------------------------
DWORD CAnyDlg::StartThread(LPVOID lpParam)
{
((CAnyDlg*)lpParam)->Thread();
return 0;
}
//-------------------------------------------------------------------------
void CAnyDlg::Thread()
{
while(m_bThread)
{
m_cstaAnyStatic.SetWindowText("Test");
}
}
//-------------------------------------------------------------------------
|
|
|
|
|
jason99 wrote:
...the while-loop doesn't break, meaning that WaitForSingleObject does never return WAIT_OBJECT_0.
Nor should it. When the Stop button is clicked, you are waiting 1/10 of a second for the secondary thread object to become signaled. Since there is no code in place to signal it, WAIT_TIMEOUT is returned. Once that happens, m_bThread is set to false , which should cause the loop in CAnyDlg::Thread() to stop, but does nothing for the loop in CAnyDlg::OnStop() , which only stops once WAIT_OBJECT_0 is returned.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
OK, that is right. The first call to WaitForSingle object will surely return WAIT_TIMEOUT. But when the bool is switched, the loop in CAnyDlg::Thread() stops. This means that the created thread will terminate sometime later. From this point on, a continous call to WaitForSingleObject should return WAIT_OBJECT_0 after some time. But that doesn't happen.
Tha fact that concerns me is that the code works if i take away the SetWindowText() in the thread or i i call PeekMessage in the WaitForSingleObject loop...this must have something to do with the message queue...
|
|
|
|
|
If this secondary thread's handle is closed while the wait is still pending, WaitForSingleObject() 's behavior is undefined.
Have you seen these two articles:
http://www.flounder.com/workerthreads.htm
http://www.flounder.com/uithreads.htm
|
|
|
|
|
One solution is a boolean variable to indicate the status of the loop.
Kuphryn
|
|
|
|
|
Aha!
m_cstaAnyStatic.SetWindowText causes a WM_SETTEXT message to be sent to the message queue. However, while in the loop in CAnyDlg::Stop, the UI thread can't process the message (this assumes that the static control and the dialog box were created by the same thread and hence share that thread's message queue).
You're effectively deadlocked.
It's typically a bad idea to directly modify any controls on the UI thread from a worker thread. It's better to define a custom message and post (not send) messages to the window to effect any changes in UI state. PostMessage just queues up the message, then returns; SendMessage blocks until the message is received by the window procedure, processed, and a response generated (either by returning from the window procedure, or by calling ReplyMessage ).
|
|
|
|
|
Good catch!! The post vs. send message problem is common, but is sometimes hidden in the problem description.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
Hi guys,
thanx for the hints! I will try the PostMessage()!
|
|
|
|
|
I execute an application in a console with ShellExecuteEx, but when this application ends I would the console's windows doesn't close because this function works like a daemon. So, how can I keep the window open?
thanks
|
|
|
|
|
chadell wrote:
...the console's windows doesn't close because this function works like a daemon. So, how can I keep the window open?
Maybe I'm reading this wrong, but first you say that the window doesn't close and then you say that you want to keep it open. Am I missing something?
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
sorry my english, david.
my problem is that the console application (executed by ShellExecuteEx) ends its execution and then closes its window, but the application needs to keep the window open until I close this(I thought to do this by the TerminateProcess with the hProcess returned by ShellExecuteEx). For more details, the application I want to run is MRTG.
thanks
|
|
|
|
|
One possible solution is to simply add a call to get() or another C++ I/O function that waits for the user to press ENTER before terminating.
Lookup ShellExecuteEx() at MSDN.
Kuphryn
|
|
|
|