|
The 1st level of the popup (the items you see first when it pops up) is pMenu->GetSubMenu(0).
So the top level items can be accessed like this:
pMenu->GetSubMenu(0)->GetMenuString(...)
If the third item (index 2) has a sub menu you could get at it like this:
pMenu->GetSubMenu(0)->GetSubMenu(2)->GetMenuString(...)
|
|
|
|
|
Maybe you have missunderstood me.
What I want is the ID/Name for the parent menu, not the childs!!
Mohammad
And ever has it been that love knows not its own depth until the hour of separation
|
|
|
|
|
Mohammad A Gdeisat wrote: What I want is the ID/Name for the parent menu, not the childs!!
ok sorry.
I don't see any functions or messages to get the parent menu from a child item.
Generally that's all known by whoever builds the menu.
You could start at the top with CWnd::GetMenu() or something and traverse the heirarchy I suppose.
|
|
|
|
|
Hello gurus,
I have a question concerning multi core programming.
I have written a simple independent thread encapsulated in a class that simply display a pixel at a random location and random color.
I can launch the thread on the CPU I want.
I have 4 x64 cores on my computer. So, when I saw the incredible speed I said to my self "ok, if it goes so fast on 1 CPU, it will go 4 time faster on 4 CPUs". So, I decided to create an array of my class that contains the thread and launch the thread on every CPUs with masks { 1, 2, 4, 8 }.
I noticed that it goes slower than it should!
Norally, as I launch 4 threads on 4 different CPUs, it can display simultaneously 4 pixel at a time, so it should give the illusion to go 4 time faster. But it is not the case.
My question is simply... WHY??? Why it goes slower than it should? What I have missed?
Thanks in advance for your answers.
Best regards.
Fred.
There is no spoon.
|
|
|
|
|
bouli wrote: Norally, as I launch 4 threads on 4 different CPUs, it can display simultaneously 4 pixel at a time
You say normally it works but when you do it it's slower? Doesn't make sense.
There's no way it will be 4 times faster. It'll be faster but not a full 4 times. I know
close to nothing about the hardware involved, but I know the processors are sharing the same video
device, the same bus, etc. so it would be impossible to get 4 times the speed.
|
|
|
|
|
That's what surprised me.
Here is the code of the thread:
class CRandomDraw<br />
{<br />
public:<br />
CRandomDraw();<br />
~CRandomDraw();<br />
<br />
void Start();<br />
void Stop();<br />
<br />
void SetCpu(int nCpu);<br />
void SetHwnd(HWND hWnd);<br />
void SetRect(RECT rect);<br />
<br />
private:<br />
BOOL m_bRunning;<br />
DWORD m_dwMask;<br />
HWND m_hWnd;<br />
HDC m_hDC;<br />
HANDLE m_hThread;<br />
HANDLE m_hEvent;<br />
RECT m_rect;<br />
<br />
int m_nCurrentCpu;<br />
<br />
static DWORD WINAPI RandomThread(LPVOID lpParameter);<br />
};<br />
#include "StdAfx.h"<br />
#include "RandomDraw.h"<br />
#include <math.h><br />
<br />
CRandomDraw::CRandomDraw()<br />
{<br />
m_bRunning=FALSE;<br />
m_hWnd=NULL;<br />
m_hDC=NULL;<br />
m_hThread=NULL;<br />
m_hEvent=NULL;<br />
m_nCurrentCpu=0;<br />
m_dwMask=1;<br />
<br />
srand((int) time(NULL));<br />
}<br />
<br />
CRandomDraw::~CRandomDraw()<br />
{<br />
Stop();<br />
<br />
::CloseHandle(m_hEvent);<br />
m_hEvent=NULL;<br />
<br />
::CloseHandle(m_hThread);<br />
m_hThread=NULL;<br />
}<br />
<br />
void CRandomDraw::SetHwnd(HWND hWnd)<br />
{<br />
m_hWnd=hWnd;<br />
m_hDC=GetDC(m_hWnd);<br />
}<br />
<br />
void CRandomDraw::SetRect(RECT rect)<br />
{<br />
m_rect=rect;<br />
}<br />
<br />
void CRandomDraw::SetCpu(int nCpu)<br />
{<br />
m_nCurrentCpu=nCpu;<br />
}<br />
<br />
void CRandomDraw::Start()<br />
{<br />
if (m_bRunning)<br />
return;<br />
<br />
m_bRunning=TRUE;<br />
<br />
m_hThread=::CreateThread(NULL, 0, RandomThread, this, CREATE_SUSPENDED, NULL);<br />
<br />
m_dwMask=(DWORD) pow(2, (double) m_nCurrentCpu);<br />
<br />
::SetThreadAffinityMask(m_hThread, m_dwMask);<br />
<br />
::ResumeThread(m_hThread);<br />
}<br />
<br />
void CRandomDraw::Stop()<br />
{<br />
if (!m_bRunning || !m_hThread)<br />
return;<br />
<br />
m_bRunning=FALSE;<br />
<br />
WaitForSingleObject(m_hEvent, INFINITE);<br />
::CloseHandle(m_hThread);<br />
m_hThread=NULL;<br />
}<br />
<br />
DWORD WINAPI CRandomDraw::RandomThread(LPVOID lpParameter)<br />
{<br />
CRandomDraw* pThis=reinterpret_cast < CRandomDraw* >(lpParameter);<br />
<br />
while (pThis->m_bRunning)<br />
{<br />
::SetPixel(pThis->m_hDC, rand() % pThis->m_rect.right, rand() % pThis->m_rect.bottom, RGB(rand() % 255, rand() % 255, rand() % 255));<br />
<br />
::Sleep(0);<br />
}<br />
<br />
SetEvent(pThis->m_hEvent);<br />
<br />
return 0;<br />
}<br />
The view call the functions like this:
In the header:
<br />
CRandomDraw m_randomDraw[CPU_COUNT];<br />
<br />
void StartAll();<br />
void StopAll();<br />
void SetHwndAll(HWND hWnd);<br />
void SetRectAll(RECT rect);<br />
In the cpp:
void CRandomView::StartAll()<br />
{<br />
for (int i=0; i<CPU_COUNT; i++)<br />
{<br />
m_randomDraw[i].SetCpu(i);<br />
m_randomDraw[i].Start();<br />
}<br />
}<br />
<br />
void CRandomView::StopAll()<br />
{<br />
for (int i=0; i<CPU_COUNT; i++)<br />
m_randomDraw[i].Stop();<br />
}<br />
<br />
void CRandomView::SetHwndAll(HWND hWnd)<br />
{<br />
for (int i=0; i<CPU_COUNT; i++)<br />
m_randomDraw[i].SetHwnd(hWnd);<br />
}<br />
<br />
void CRandomView::SetRectAll(RECT rect)<br />
{<br />
for (int i=0; i<CPU_COUNT; i++)<br />
m_randomDraw[i].SetRect(rect);<br />
}<br />
<br />
BOOL CRandomView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)<br />
{<br />
BOOL bRet=CView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);<br />
<br />
SetHwndAll(m_hWnd);<br />
StartAll();<br />
<br />
return bRet;<br />
}<br />
<br />
void CRandomView::OnDestroy()<br />
{<br />
StopAll();<br />
CView::OnDestroy();<br />
<br />
}
I think there is nothing special...
Where is it wrong???
There is no spoon. t
|
|
|
|
|
Can you perhaps check the "Ignore HTML tags in this message (good for code snippets)"
checkbox on your reply?
Hard to read your code with < and > missing
|
|
|
|
|
Sure
Random header:
#pragma once
class CRandomDraw
{
public:
CRandomDraw();
~CRandomDraw();
void Start();
void Stop();
void SetCpu(int nCpu);
void SetHwnd(HWND hWnd);
void SetRect(RECT rect);
private:
BOOL m_bRunning;
DWORD m_dwMask;
HWND m_hWnd;
HDC m_hDC;
HANDLE m_hThread;
HANDLE m_hEvent;
RECT m_rect;
int m_nCurrentCpu;
static DWORD WINAPI RandomThread(LPVOID lpParameter);
};
Random implementation (cpp):
#include "StdAfx.h"
#include "RandomDraw.h"
#include <math.h>
CRandomDraw::CRandomDraw()
{
m_bRunning=FALSE;
m_hDC=NULL;
m_hThread=NULL;
m_hEvent=CreateEvent(NULL, TRUE, TRUE, NULL);
m_nCurrentCpu=0;
m_dwMask=1;
srand((int) time(NULL));
}
CRandomDraw::~CRandomDraw()
{
Stop();
::CloseHandle(m_hEvent);
m_hEvent=NULL;
}
void CRandomDraw::SetHwnd(HWND hWnd)
{
m_hWnd=hWnd;
m_hDC=::GetDC(m_hWnd);
}
void CRandomDraw::SetRect(RECT rect)
{
m_rect=rect;
}
void CRandomDraw::SetCpu(int nCpu)
{
m_nCurrentCpu=nCpu;
}
void CRandomDraw::Start()
{
if (m_bRunning)
return;
m_bRunning=TRUE;
m_hThread=::CreateThread(NULL, 0, RandomThread, this, CREATE_SUSPENDED, NULL);
m_dwMask=(DWORD) pow(2, (double) m_nCurrentCpu);
::SetThreadAffinityMask(m_hThread, m_dwMask);
::ResumeThread(m_hThread);
}
void CRandomDraw::Stop()
{
if (!m_bRunning || !m_hThread)
return;
m_bRunning=FALSE;
WaitForSingleObject(m_hEvent, INFINITE);
::CloseHandle(m_hThread);
m_hThread=NULL;
}
DWORD WINAPI CRandomDraw::RandomThread(LPVOID lpParameter)
{
CRandomDraw* pThis=reinterpret_cast<CRandomDraw*>(lpParameter);
while (pThis->m_bRunning)
{
::SetPixel(pThis->m_hDC, rand() % pThis->m_rect.right, rand() % pThis->m_rect.bottom, RGB(rand() % 255, rand() % 255, rand() % 255));
::Sleep(0);
}
SetEvent(pThis->m_hEvent);
return 0;
}
Calls in the SDI view header:
...
private:
CRandomDraw m_randomDraw[CPU_COUNT];
void StartAll();
void StopAll();
void SetHwndAll(HWND hWnd);
void SetRectAll(RECT rect);
afx_msg void OnDestroy();
...
Implementation in the SDI (cpp):
...
BOOL CRandomView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
BOOL bRet=CView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
SetHwndAll(m_hWnd);
StartAll();
return bRet;
}
...
void CRandomView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
RECT rect;
GetWindowRect(&rect);
SetRectAll(rect);
}
void CRandomView::StartAll()
{
for (int i=0; i<CPU_COUNT; i++)
{
m_randomDraw[i].SetCpu(i);
m_randomDraw[i].Start();
}
}
void CRandomView::StopAll()
{
for (int i=0; i<CPU_COUNT; i++)
m_randomDraw[i].Stop();
}
void CRandomView::SetHwndAll(HWND hWnd)
{
for (int i=0; i<CPU_COUNT; i++)
m_randomDraw[i].SetHwnd(hWnd);
}
void CRandomView::SetRectAll(RECT rect)
{
for (int i=0; i<CPU_COUNT; i++)
m_randomDraw[i].SetRect(rect);
}
void CRandomView::OnDestroy()
{
StopAll();
CView::OnDestroy();
// TODO: Add your message handler code here
}
...
Maybe I have missed something.
As I said, normally, the pixels should be displayed CPU_COUNT faster because there are CPU_COUNT threads running on separate CPU, while each CPU runs 1 thread. So, 4 pixels at a time should be displayed. But it is much slower than running 1 thread. This is a paradox. And what I don't understand.
Thanks to help me to solve my problem
Best regards.
Fred.
There is no spoon.
|
|
|
|
|
What happens if you remove the ::Sleep(0); call from your thread proc (don't let the threads give
up any of their time slice)?
You're still not going to get 4 times as fast since you have device contention at the display
device.
I wouldn't think it would be slower though
|
|
|
|
|
Hi,
Sleep(0) is supposed to free the thread's quantum allocated by the system.
I removed it but it is still slower as if it would run on 1 CPU which is paradoxal.
There is no spoon.
|
|
|
|
|
bouli wrote: Sleep(0) is supposed to free the thread's quantum allocated by the system.
Right - I was wondering what would happen if you let the threads use their entire time-slice;
I don't know what goes on with processor cache and bus and RAM contention but just at the
SetPixel() call alone, only one thread will be able to write a pixel at a time unless your video
device can parallel process the calls.
I don't think it's paradoxal. I think the fastest performance you could get would be to have one
thread that does the IO (output a pixel) and 3 threads calculating the random coordinates and
feeding them to the pixel-outputter-thread. Just a guess, I could be way off
When you run it what does performance monitor show for CPU usage?
|
|
|
|
|
Example fromm Google search ("multicore percent faster"):
From Performance Analysis and Multicore Processors[^]...
"One of the side effects of multicore technology is that CPU-bound applications can
potentially run twice as fast on dual-core processors, whereas memory-bound applications may only
run 50 percent faster. I/O-bound applications may not run any faster"
|
|
|
|
|
PROBLEM DESCRIPTION
I have a CFormView based SDI application. There is a button and a Editbox (m_Progress , a control category CEdit variable, indicating program progress) on the form. A lengthy task will be started by clicking the button. Usually the task will take several hours. While the process is running, users may use other applications, such as WORD, EXCEL,etc,. When users get back to the process to see its progress. The window cannot be maxmized. To solve this problem, I read some articles. A lot of articles suggest that thread should be used.
So, i decide to use a worker thread to solve this problem. To this end, I move the code in the original button-cick handler to a function (SubFunc())of a class (MyClass). In the new button-click handler I first creat an instance of MyClass. Then, pass the instance to AfxBeginThread() to create a worker thread. The above steps are implented as follows.
UINT MyThreadProc(LPVOID pParam)
{
MyClass* pObject = (MyClass*)pParam;
if (pObject == NULL)
{
return -1;
}
else
int test = pObject->SubFunc();
return 0;
}
}
void CHhhhView::OnButton1()
{
MyClass *objMyClass = new MyClass;
AfxBeginThread(MyThreadProc, objMyClass);
}
In SubFunc(), I use following statements to send the string "9999" to m_Progress. Specially, ((CMDIFrameWnd*)AfxGetMainWnd()->GetActiveWindow())->GetActiveDocument() is used.
CDocument* pp = ((CMDIFrameWnd*)AfxGetMainWnd()->GetActiveWindow())->GetActiveDocument();
POSITION vv = pp->GetFirstViewPosition();
POSITION pos = pp->GetFirstViewPosition();
if (pos != NULL)
{
CHhhhView* pView = (CHhhhView*)pp->GetNextView(pos);
if(pView!=NULL)
{
pView->m_Progress.SetWindowText("9999");
pView->UpdateWindow();
}
}
However, ((CMDIFrameWnd*)AfxGetMainWnd()->GetActiveWindow())->GetActiveDocument() works
only when objMyClass is NOT called
in a worker thread.
That is, objMyClass is called in the following way,
void CHhhhView::OnButton1()
{
MyClass mc;
mc.SubAdd();
int itmp = mc.m_itmp;
}
I noticed an artical
http://www.codecomments.com/archive372-2006-4-890607.html[^], which highly associated with my problem. However, I still could not figure out the solution, as I am a newbie to MFC.
* Am I in the right direction to solve the problem correctly caused by lengthy task by using a worker thread?
* What is a good way to wire the CEdit control and the varible updated in the SubFunc() running in a worker thread.
Please help me. This problem has stumped me for serveral days .
-- modified at 17:25 Saturday 4th November, 2006
|
|
|
|
|
GetActiveWindow() is thread-specific. You have no active windows in your worker thread.
Why not add a CHhhhView* member to your MyClass class (pass it in in the constructor):
class MyClass
{
CHhhhView *pView;
public:
MyClass(CHhhhView *view) {pView = view;}
};
void CHhhhView::OnButton1()
{
MyClass *objMyClass = new MyClass(this);
AfxBeginThread(MyThreadProc, objMyClass);
}
Now you can use pView in MyClass instead of ((CMDIFrameWnd*)AfxGetMainWnd()->GetActiveWindow()).
|
|
|
|
|
:-DThank you Mark very much for your reply. It works for me.
|
|
|
|
|
One more question about this topic.
Where and how should the pointer 'objMyClass' be deleted to prevent memory leak. I think this should be done at the end of SubFunc(). However, I am not very sure.
|
|
|
|
|
cy163@hotmail.com wrote: Where and how should the pointer 'objMyClass' be deleted to prevent memory leak.
Any time after the pObject->SubFunc() call (obviously)
There's alot of people who object to deleting objects in a different thread than the thread the
object was created in. If you are using new/delete this is perfectly legal to do, so IMO it
comes down to preference.
If it's clear in the code that you create an object (using new) and send it off to a worker
thread to be processed, and that the worker thread will delete it when it's finished, then delete
it in the thread proc when you're finished with it.
If you want to delete it in the same thread it was created in (the UI thread in your example)
then you could use PostThreadMessage() from the worker thread to send the pointer back to the UI
thread for deletion when it's finished with it. The worker thread would need to know which thread
it came from to know where to post the message to.
cy163@hotmail.com wrote: I think this should be done at the end of SubFunc(). However, I am not very sure.
I personally wouldn't do it IN the SubFunc() function. That would be, IMO, too buried to be clear
in the code what's going on. Right after the pObject->SubFunc() call a "delete pObject;" would
be fine.
I would just make sure to document it well in the code with comments so when you possibly enhance
the code later you know exactly where objects are bing deleted, something like this:
void CHhhhView::OnButton1()
{
MyClass *objMyClass = new MyClass;
AfxBeginThread(MyThreadProc, objMyClass);
}
Whatever it takes to make sure you always know that you shouldn't use objMyClass later because
at any time the worker thread will delete it
|
|
|
|
|
Thank you Mark for your clear explanation.
One more further question, also about mem leak. i have some dynamically allocated variables (using malloc(), new) in SunFunc(). I wonder if those allocated mem can be deallocated automatically after the thread finished successfully. Or, i have to take care of the memory releasing things myself.
Moreover, could you please talk about how to terminate the thread before SubFunc() reaches its end in my example. I refer to some articles. They suggested to use CEvent and WaitForSingleObject(), as well as AfxEndThread().
I do not how to combine them to terminates a thread from another thread (main thread, in my case).
Thank you for your valuable time
-- modified at 6:10 Monday 6th November, 2006
|
|
|
|
|
Hi,
I want to create a child window with menu like in a SDI application from a dialog based application. How to create it?
Cyber Friend
|
|
|
|
|
Is it possible to reallocate using operator new?
// C
some_ptr = malloc( sizeof( some_type ) * n );
... // change "n"
some_ptr = realloc( sizeof( some_type ) * n );
// C++
some_ptr = new some_type[n];
... // change "n"
// Now what?
Best regards
hint_54
|
|
|
|
|
The short answer is no. Either use a combination of malloc and realloc as in your example, or use the keyword new and copy the contents over to a larger buffer.
|
|
|
|
|
|
Use an STL collection such as vector , and you won't have to worry about the memory allocation.
|
|
|
|
|
Hi
I need a program that convert date to shamsi
thank you
|
|
|
|
|
|