|
I've been stuck for 2 days with controlling list control in mfc threads. your code helped me a lot! thank you!
|
|
|
|
|
Too too basic and highly uninformative
|
|
|
|
|
I can understand this as a example on how to force the use but more information should be present on why this is a bad idea and why the limitations exist...
|
|
|
|
|
As was pointed out, the code allocates a THREADSTRUCT object but fails to free it.
However, I don't even see why this is needed. Just pass this to the function and you have your pointer to the class instance. No additional structures, and no additional allocations.
|
|
|
|
|
This was the first hit I got on google when searching for "afxBeginThread member function", so I feel need to make it clear that this solution is obviously flawed and incorrect.
As pointed out before, the proposed solution will cause a memory leak because delete on THREADSTRUCT is not called. If, however, one calls delete after AfxBeginThread, we will get an undeterministic result. For if the thread for some reason takes a long time to start, delete may be called before the static function can read the parameters in the THREADSTRUCT, and then we have no idea what the memory area the pointer points to contains.
|
|
|
|
|
This trick is great, simple and very useful.
TXS
|
|
|
|
|
Hi!
I'm trying to implement a multi-client server and when i run my code y receive an Access Violation on the ThreadProc when i call conn->Connect.Receive. The struct Conexiones is well defined? How can my ListenSocket could hear and accept new connections. This is part of my code:
struct Conexion *Conexiones=Conexiones=new struct Conexion [MAX_CONEXIONES];
void CSockDlgServer::OnAccept()
{
int i=0;
while ((i<max_conexiones) &&="" (conexiones[i].status="=1))
" i++;
="" m_slistensocket.accept(conexiones[i].connect);=""
="" startthread();
}
void="" csockdlgserver::startthread()
{
="" int="" i="0;
" while="" conexiones[i].cliente="hSocket;
" conexiones[i].servidor="m_sListenSocket.m_hSocket;
" conexiones[i].status="1;
" conexiones[i].connect.setparent(this);
="" cwinthread="" *thread;
="" thread="AfxBeginThread(ThreadProc,&Conexiones[i]);
" thread-="">m_nThreadID=Conexiones[i].Connect.m_hSocket;
}
UINT CSockDlgServer::ThreadProc(LPVOID _param)
{
struct Conexion * conn=(struct Conexion *) param;
char *pBuf = new char[1025];
int iBufSize=1024;
int iRecvd;
// recibimos el mensaje
iRecvd=conn->Connect.Receive(pBuf,iBufSize); // here is de Access Violation
if (iRecvd==SOCKET_ERROR)
{
return 1;
}
else
{
// i do some operation with a data structure
}
return 0;
}
Please Help Me!
|
|
|
|
|
Hello,
I am very interested in this method, I tried to implement it but I had a problem.
The fact is, in my case, I am not using a CDialog derived class but a class like this one :
class ATL_NO_VTABLE CPropPage :
public CComObjectRootEx<ccomsinglethreadmodel>,
public CComCoClass<cproppage, &clsid_proppage="">,
public IPropertyPageImpl<cproppage>,
public CDialogImpl<cproppage>
{
So I can not implement the DoDataExchange function that is (I think) important to have a good behavior of the software.
The thread starts because I see the MessageBox "Thread is started!" but the progress bar is not updated with the different step of progression.
Is the DoDataExchange function the problem ? Somebody has other ideas ?
Thanks.
Vianney
|
|
|
|
|
This program is very simple but nice !It is easy for me to study it .Thanks a lot!
from China 2007-2-6
LXS
|
|
|
|
|
I am doing some OpenGL drawing in MFC view.
I have a OpenGL class which is used as the base class for MFC view. Then using display lists i have tried to put the drawing on the view. But in tha case of huge point sets, the View doest respond because of openGL drawing.
Then i thought of using threads for openGL.Now i want to implement a thread for drawing openGL stuff.
I have one static UINT threadfunc(LPVOID param) and void threadfunc() declared.
Then i have tried to begin the thread.
I did not get any compilation, linker errors.
But i was unsuccessful in getting the drawing stuff.
Can anyone help me?
|
|
|
|
|
This is a slight different question than the previous memory leak one. I have converted the demo project to Visual studio 7.1 and compiled it under the debug mode, and this is what I get when I clicked on "Start" to run the thread.
ThreadDemo.exe': Loaded 'C:\Program Files\Yahoo!\Messenger\msvcr71.dll', No symbols loaded.
Detected memory leaks!
Dumping objects ->
thrdcore.cpp(311) : {78} client block at 0x00326A50, subtype c0, 68 bytes long.
a CWinThread object at $00326A50, 68 bytes long
c:\code\thread2\threaddemo\threaddemodlg.cpp(196) : {77} normal block at 0x00324B80, 4 bytes long.
Data: < > E8 FD 12 00
Object dump complete.
The thread 'Win32 Thread' (0xdb4) has exited with code 0 (0x0).
The program '[3796] ThreadDemo.exe: Native' has exited with code 0 (0x0).
------------------------------------
This is very confusing. Please help
jiac
|
|
|
|
|
Your idea had saved my ass.
I use it for multithread receives with sockets.
THANKS, man.
|
|
|
|
|
Hi Enis,
Thank you so much for this little technique. I've found it very useful indeed. However, I've hit one problem which is that no matter how hard I try I can't avoid getting a memory leak when I run it.
The leak is always 4 bytes long and I'm convinced it's the THREADSTRUCT. I've tried to delete it but have found it virtually impossible to get rid of.
How and where do you delete this object? Can you help?
Many thanks,
Simon
|
|
|
|
|
Can't you just delete ts structure within the StartThread function; this seems logical since ts points to the memory space that was allocated.
-- Darin
|
|
|
|
|
Add "Delete ts;",Before "return 1;",It Should Be Solve Memory Leak Problem.
|
|
|
|
|
Thanks a lot. Your article really got me out of a fix. I have though 1 problem. I have a class X that instantiates a class CSerialPort (freeware).
I am spawning a thread so that I can wait for a COM event. I tried WaitEvent like so
ts->this->m_Port.WaitEvent(dwMask);
it is exceptioning at this point. Could someone tell me why that is happening and what I could do about it?
Thanks
|
|
|
|
|
hey
Tell me please how to stop the thread in between from some button click event.
I am using pThread->SuspendThread()
Thread is stopped but when i return to my Main form program hangs.
Thanks
Shailesh
|
|
|
|
|
Hy,
I didn't test the exact code you wrote in your previous post, but I can sugest you a solution using Events. (the code below is typed so it might not be such accurate)
HANDLE yourEvent;
yourEvent = ::CreateEvent (NULL,
TRUE,
FALSE,
NULL
);
CWinThread* pWorkerThread = NULL;
pWorkerThread = AfxBeginThread (ThreadFunc, ...);
pWorkerThread->m_bAutoDelete = FALSE;
if (::WaitForSingleObject (pWorkerThread->m_hThread, INFINITE) == WAIT_OBJECT_0)
if (pWorkerThread != NULL)
::GetExitCodeThread (pWorkerThread->m_hThread, &dwExitCode);
CloseHandle(yourEvent);
delete pWorkerThread;
I hope this helps.
You can also check Joseph M. Newcomer's great articles about threads
(http://www.codeproject.com/threads/usingworkerthreads.asp[^])
Enis Arif
-----------
"I am enough of an artist to draw freely upon my imagination. Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world." (Albert Einstein)
|
|
|
|
|
From PEPE2207
Hi, Enis, Recently I tried your threaddemo article and I found it works fine, but I am a bit confuse because I can not discover where is deleted the _param pointer releasing the heap memory asigned to the ts THEADSTRUCT instance that you were using the new istruction. Sincerely
|
|
|
|
|
Hey I am using this code in my thread as
void CUploadForm::OnButtonUpload()
{
THREADSTRUCT *_param = new THREADSTRUCT;
_param->_this = this;
pThread = AfxBeginThread (StartThread,_param );
}
UINT CUploadForm::StartThread (LPVOID param)
{
THREADSTRUCT* ts = (THREADSTRUCT*)param;
ts->_this->PreparePostData();
AfxEndThread(0);// here
return 1;
}
Now i want to stop this thread process on some button click event but when return to my form my program hangs. I am stopping as:
void CUploadForm::OnButtonCancel()
{
if(pThread)
{
pThread->m_bAutoDelete = FALSE;
UINT aa = pThread->SuspendThread( );
SetDlgItemText(IDC_EDIT_RESPONSE,_T("Process Stopped by user."));
pThread = NULL;
}
}
and when i press the button to return to my main program it hangs any idea
void CUploadForm::OnButtonReturn()
{
CMainFrame* pFrame = (CMainFrame*)GetParentFrame();
pFrame->SwitchToForm(IDD_NOPDCITATION_FORM);
pFrame->SetWindowText(_T("Cite Capture"));
}
Please help me
shailesh
|
|
|
|
|
I used this example and it works fine if i do it exactly like he has. But what if i actually want to do something inside the thread. I can't.
I have member control called m_ball1 and a HICON called m_h0;
I want to update the m_ball1 within the thread but i can't.
i keep getting the error
error C2228: left of '.SetIcon' must have class/struct/union type
error C2597: illegal reference to data member 'CCash3mfcDlg::m_h0' in a static member function
I have everything exactly like the author of this demo has except my Classname is different I used CCash3mfcDlg.
I have this in the cpp. If i // it out the program works just like the demo.
What am I doing wrong cause i would really like to incorporate this into my program.
UINT CCash3mfcDlg::StartThread(LPVOID param)
{
THREADSTRUCT* ts = (THREADSTRUCT*)param;
//here is the time-consuming process which interacts with your dialog
AfxMessageBox ("Thread is started!");
ts->_this->m_processstatus.SetRange (0, 1000);
while (ts->_this->m_processstatus.GetPos () < 10000000)
{
Sleep(500);
////////////////////THE MENTIONED ERRORS ARE CAUSED BY THIS ADDITION////////
m_ball1.SetIcon(m_h0);
////////////////////////////////////////////////////////////////////////////
ts->_this->m_processstatus.StepIt ();
}
//you can also call AfxEndThread() here
return 1;
}
Just starting to get into Visual C++ so give me some slack please.
|
|
|
|
|
I am just guessing here, based on my own challenges with multi-thread, but perhaps it will help you (?)
The multi thread functions must be static, and there are restrictions on the kinds of access static functons can have. I am guessing m_h0 is not static and therefore not directly acessible by the static multi thread func.
Basically a static function (and static variables) only exists once in memory, regardless of the number of times you instantiate an object from a class. This means a static function cannot know about the specific instance of an object and ita members (at least not directly.
I.e. if class CTest has member NotStatic, and static member Static, then
CTest T1;
CTest T2;
T1.NotStatic = 1;
T2.NotStatic = 2;
ASSERT( T1.NotStatic != T2.NotStatic ); //ok, no conflict
T1.Static = 1; //Static now 1
T2.Static = 2; //Static of ALL CTests now 2!!!
ASSERT( T1.Static != T2.Static ); //FAILS - CTest.Static all the same veriable.
A static function in CTest using NonStatic, would not directly know which instance (T1 or T2) to use, and therefore fails.
However, if you somehow pass the static function enough info to resolve the referencing (usually by a this pointer), you are ok.
Therefore you might try referencing m_h0 using the _this pointer - as far as I can see the THREADSTRUCT includes a _this pointer, which would let the static function access the specific instance of CCash3mfcDlg which holds the specific instance of m_h0. I am guessing the m_ball1 is also non static.
//m_ball1.SetIcon(m_h0); changed to use this pointer
ts->_this->m_ball1.SetIcon(ts->_this->m_h0);
Nitpicking: Why set the icon in a thread, rather than before calling thread in an initialize function? If you have to do it you should probably have a function
CCash3mfcDlg::SetIcon() {
m_ball1.SetIcon(m_h0);
}
and call it from your thread like this
ts->_this->SetIcon();
PS If you are just learning C++, you might want to start easier than multi threading , but good luck, I admire your courage.
|
|
|
|
|
Thanks for your help and encouragement on the project. I actually completed it. You were right about the static pass in the thread. here is what i did.
And as for the setting of the icon I did that for a specific reason. Maybe not the most suffient at the time but I am still learning. I have 3 icons on the screen to represent balls from 0 to 9 and i randomly generate a number sequence consisting of three numbers while the thread runs. and it displays that number sequence represented as balls. and I run it in the thread so it makes the balls look as if they are spinning.
here is a portion of the source pertaining to the thread.
http://rafb.net/paste/results/rx590089.html
Thanks again,
Win32newb
"Making windows programs worse than they already are"
|
|
|
|
|
Glad I could help
BTW, the link http://rafb.net/paste/results/rx590089.html does not seem to work
As for my nitpick about setting icons, please ignore that.
If you are trying to do sprite like animation (using icons because they can have transparency) running the "frames" from a worker thread seems like a good solution (IMO).
Jens
|
|
|
|
|
It was my understanding that you should not pass pointers to CWnd objects like dialogs into threads, but pass the handle (using GetSafeHwnd), and then retrieve pointer in thread using CWnd* pWnd = CWnd::FromHandle(pParam).
But, I might be wrong - I am here becuse the examples showing the above does not seem to work for me when trying to give me access to a dialog from within a thread
(the returned pointer seems to point to some other uninitialized instance)
If anyone knows about this I would love to hear from you....please?
Example: CMyDlg:CDialog has member variable int m_iX = 5424992;
CMyDlg::OnBtnGo{) {
...
AfxBeginThread(MyProcc, this->AfxGetSafeHwnd())
...
}
UINT MyProcc(LPVOID pParam) {
CMyDlg* pDlg = (CMyDlg*)(CWnd::FromHandlePermanent((HWND)pParam));
TRACE1("X=%i", pDlg->m_iX;
}
results in 4258440 not 5424992 ?????
Incidentally, pDlg != this pointer in dlg,
but pParam = m_hWnd of dialog
Arrgghhhhh!!!
Any help on HOW I can access a member in MuDlg from a thread would be appreciated.
Jens
|
|
|
|