|
Mark,
I think you are right, I am thinking I need stop inheriting a ClxThread and declare a clxthread object within the mainloop and poll_lenze class. However, I have been struggling to pass a void ThreadFunc(void) into CreateNewThread(PTHREADFUNC pThreadFunc); which turns the function ThreadFunc into working thread/function. However, if i create a function in mainloop like this static UINT WINAPI MaintainingThreadProc(LPVOID pParam); and pass it into CreateNewThread(PTHREADFUNC pThreadFunc) Than, MaintainingThreadProc() function becomes a worker thread. I really would like to just pass the stardard void ThreadFunc(void) function prototype if possible.
class ClxThread<br />
{<br />
public:<br />
ClxThread();<br />
virtual ~ClxThread();<br />
<br />
typedef unsigned (__stdcall *PTHREADFUNC)(void *);<br />
bool CreateNewThread(void);<br />
bool CreateNewThread(PTHREADFUNC pThreadFunc);<br />
bool Wait();
bool Suspend();
bool Resume();
bool Kill();
bool IsActive();
<br />
virtual void ThreadEntry(){ }<br />
virtual void ThreadExit(){ }<br />
virtual void ThreadRun(){ }<br />
<br />
static UINT WINAPI _ThreadFunc(LPVOID pParam);<br />
<br />
public:<br />
HANDLE m_hThread;
UINT uiThreadId;
<br />
bool m_bActive;
DWORD m_lpId;
};<br />
Scott Dolan
Jernie Corporation
Engineering & Manufacturing
Software, Hardware, & Enclosures
|
|
|
|
|
ScotDolan wrote: I am thinking I need stop inheriting a ClxThread and declare a clxthread object within the mainloop and poll_lenze class.
Maybe Whatever is best for your design. I suppose since mainloop and poll_lenze both have
associated threads, they could each derive from ClxThread, but mainloop, then, shouldn't be
derived from poll_lenze since mainloop is not a poll_lenze.
ScotDolan wrote: if i create a function in mainloop like this static UINT WINAPI MaintainingThreadProc(LPVOID pParam); and pass it into CreateNewThread(PTHREADFUNC pThreadFunc)
I'm not sure how you've implemented your ClxThread class, but from the header info,
CreateNewThread(PTHREADFUNC pThreadFunc) needs as a parameter a pointer to a function declared as
unsigned __stdcall func(void *). You shouldn't be able to pass a pointer to a function declared
as UINT WINAPI MaintainingThreadProc(LPVOID pParam).
Since you've put a nice little wrapper around a thread, I'm not sure why you need to pass a
thread proc in...
Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
ScotDolan wrote: However, I have been struggling to pass a void ThreadFunc(void) into CreateNewThread(PTHREADFUNC pThreadFunc); which turns the function ThreadFunc into working thread/function.
Why would you do that. Wouldn't a thread class encapsulate the HANDLE and the Thread function?
led mike
|
|
|
|
|
The purpose of the thread class is to make simple functions that consolidate, hide all the mondain task that need to be performed to start, kill, suspend, resume, a thread. The object is to try to prevent any Operating System specific code from getting into the my mainloop and poll-lenze code. This will make it easier for me to port the code over to Linux, Unix or any other os that supports C++. This is why the i use ThreadEnter(),ThreadRun(), and ThreadExit() can all be override. Because, ThreadEnter(),ThreadRun(), and ThreadExit() get called in the worker thread. other object is to keep the create a spreate function where the thread code goes.
The end results is that when it comes time to port the code over to a new Os, i should only have to rewrite ClxThread.
<br />
#pragma once<br />
<br />
<br />
class ClxThread<br />
{<br />
public:<br />
ClxThread();<br />
virtual ~ClxThread();<br />
<br />
typedef unsigned (__stdcall *PTHREADFUNC)(void *);<br />
bool CreateNewThread(void);<br />
bool CreateNewThread(PTHREADFUNC pThreadFunc);<br />
bool Wait();
bool Suspend();
bool Resume();
bool Kill();
bool IsActive();
<br />
virtual void ThreadEntry(){ }<br />
virtual void ThreadExit(){ }<br />
virtual void ThreadRun(){ }<br />
<br />
static UINT WINAPI _ThreadFunc(LPVOID pParam);<br />
<br />
public:<br />
HANDLE m_hThread;
UINT uiThreadId;
<br />
bool m_bActive;
DWORD m_lpId;
};<br />
#include "stdafx.h"<br />
#include ".\ClxThread.h"<br />
#include <process.h><br />
<br />
<br />
ClxThread::ClxThread()<br />
{<br />
m_hThread = NULL; <br />
m_bActive = false;<br />
uiThreadId = NULL;<br />
}<br />
<br />
<br />
ClxThread::~ClxThread()<br />
{<br />
Kill();<br />
}<br />
<br />
bool ClxThread::CreateNewThread(PTHREADFUNC pThreadFunc)<br />
{<br />
if( m_hThread == NULL )<br />
{<br />
<br />
<br />
<br />
m_hThread = (HANDLE)_beginthreadex(NULL, 0, pThreadFunc, this, CREATE_SUSPENDED, &uiThreadId);
<br />
if ( NULL != m_hThread)<br />
{<br />
ResumeThread( m_hThread );<br />
m_bActive = true;<br />
return true;<br />
}else{<br />
m_bActive = false;<br />
<br />
}<br />
}<br />
<br />
return true;<br />
}<br />
<br />
bool ClxThread::CreateNewThread(void)<br />
{<br />
if( m_hThread == NULL )<br />
{<br />
<br />
<br />
<br />
m_hThread = (HANDLE)_beginthreadex(NULL, 0, _ThreadFunc, this, CREATE_SUSPENDED, &uiThreadId);
<br />
if ( NULL != m_hThread)<br />
{<br />
ResumeThread( m_hThread );<br />
m_bActive = true;<br />
return true;<br />
}else{<br />
m_bActive = false;<br />
<br />
}<br />
}<br />
<br />
return true;<br />
}<br />
<br />
<br />
bool ClxThread::Suspend(void)<br />
{<br />
m_bActive = false;<br />
return (-1 != SuspendThread(m_hThread));
}<br />
<br />
<br />
<br />
bool ClxThread::Kill(void)<br />
{<br />
if( TerminateThread(m_hThread, 1) )
{<br />
m_hThread = NULL;<br />
m_bActive = false;<br />
return 1;<br />
}else{<br />
return 0;<br />
}<br />
}<br />
<br />
<br />
<br />
bool ClxThread::Resume(void)<br />
{<br />
m_bActive = true;<br />
return (-1 != ResumeThread(m_hThread));
}<br />
<br />
<br />
<br />
bool ClxThread::Wait(void)<br />
{<br />
return (WAIT_OBJECT_0 == WaitForSingleObject(m_hThread, INFINITE));<br />
}<br />
<br />
<br />
<br />
bool ClxThread::IsActive(void)<br />
{<br />
return m_bActive;<br />
}<br />
<br />
<br />
<br />
<br />
<br />
UINT WINAPI ClxThread::_ThreadFunc(LPVOID pParam)<br />
{<br />
ClxThread* pThis = reinterpret_cast<ClxThread*>( pParam );<br />
_ASSERTE( pThis != NULL );<br />
<br />
pThis->ThreadEntry();
pThis->ThreadRun();<br />
pThis->ThreadExit();
<br />
pThis->m_bActive = false;<br />
pThis->m_hThread = NULL;<br />
pThis->m_lpId = NULL;<br />
<br />
return 1L;<br />
}
Scott Dolan
Jernie Corporation
Engineering & Manufacturing
Software, Hardware, & Enclosures
|
|
|
|
|
But again, why do you need a member function that takes a function pointer as an argument if
you've encapsulated the threadproc so nicely? Your virtual functions expose derived classes to
the threadproc generically.
Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
I don't know why you have:
bool CreateNewThread(PTHREADFUNC pThreadFunc);<br />
virtual void ThreadEntry(){ }<br />
virtual void ThreadExit(){ }
It would seem the virtual ThreadRun() would be a complete implementation alone.
led mike
|
|
|
|
|
The purpose of bool CreateNewThread(PTHREADFUNC pThreadFunc); is so ClxThread can be used without having to be inherited. So, i can declare a ClxThread object inside of mainloop instead of inheriting clxthread. Then, i pass in the member function of mainloop into ClxThread define object and it will run in a different thread. This way, i can uses ClxThread as a inherited object or static object.
This would prevent the dreaded diamond effect.
Scott Dolan
Jernie Corporation
Engineering & Manufacturing
Software, Hardware, & Enclosures
|
|
|
|
|
That makes no sense at all. In that scenario the class has no control over the thread function and therefore the concept of encapsulation does not exist.
ScotDolan wrote: The purpose of bool CreateNewThread(PTHREADFUNC pThreadFunc); is so ClxThread can be used without having to be inherited. So, i can declare a ClxThread object inside of mainloop instead of inheriting clxthread.
For that scenario why wouldn't you declare an inherited class "inside of mainloop"?
led mike
|
|
|
|
|
For that scenario why wouldn't you declare an inherited class "inside of mainloop"?
Mike,
That is exactly what I am trying to do. However, I want mainloop to inherit ClxThread. but i also need it to inherit a Poll_Invertors. The problem is Poll_Invertors also inherits a ClxThread to create its own thread. The results is i end up with only one thread even being started ie basicly dreaded diamond.
mainloop
/ \
/ \
/ \
/ \
ClxThread Poll_Invertors
\
\
\
ClxThread
The mainloop code
<br />
class mainloop : public Poll_Invertors, public ClxThread<br />
{<br />
public:<br />
mainloop();<br />
~mainloop();<br />
void Start(void){ CreateNewThread( ); };
protected: <br />
<br />
void init_mc362X(void);<br />
bool read_mc362x(void);<br />
bool read_lenze_cfg_sheet(void);<br />
bool read_independencer( void );<br />
<br />
private: <br />
void ThreadRun( void );
MC362X_MOTION isacard;
ClxUdp cmd_socket;
ClxUdp data_socket;
}<br />
The Poll_Invertors Header
<br />
lass LENZE_8200_MOTION : public ClxThread, protected CLX_LENZE_8200<br />
{<br />
public:<br />
LENZE_8200_MOTION(void);<br />
~LENZE_8200_MOTION(void);<br />
<br />
public:<br />
bool init_lenze8200( int comm_port, int baud_rate, long timeout_ms, int maxtxfailures );<br />
bool start_lenze8200(void){ return CreateNewThread(); }<br />
<br />
void pitch_set_address( char address ){ return SetAddress( &pitch_axis_data, address ); }; ...<br />
char pitch_get_address( void ){ return GetAddress( &pitch_axis_data ); }; <br />
<br />
private: <br />
void ThreadRun(void);
void RunAll( void ); <br />
<br />
LNZ82_INVRT_DATA pitch_axis_data;<br />
LNZ82_INVRT_DATA roll_axis_data;<br />
LNZ82_INVRT_DATA lift_axis_data;<br />
LNZ82_INVRT_DATA counterweight_axis_data;<br />
ClxSafeQue<char> m_sqInvertorsCmdQue;<br />
char m_iInvertorsPollState;<br />
<br />
char pitch_init(LNZ82_INVRT_DATA *axis);<br />
char roll_init(LNZ82_INVRT_DATA *axis); <br />
char lift_init(LNZ82_INVRT_DATA *axis);<br />
char counterweight_init(LNZ82_INVRT_DATA *axis);<br />
<br />
<br />
<br />
void SetAddress( LNZ82_INVRT_DATA *axis, char address ); <br />
char GetAddress( LNZ82_INVRT_DATA *axis ); <br />
void SetOperatingVoltage( LNZ82_INVRT_DATA *axis, int volts ); <br />
char GetOperatingVoltage( LNZ82_INVRT_DATA *axis); <br />
bool GetOutputVoltage( LNZ82_INVRT_DATA *axis, double *dTemp); <br />
bool GetOutputCurrent( LNZ82_INVRT_DATA *axis, double *dTemp); <br />
bool GetOutputFrequencey( LNZ82_INVRT_DATA *axis, double *dTemp); <br />
bool GetOutputTemperature( LNZ82_INVRT_DATA *axis, double *dTemp); <br />
bool GetBusVoltage( LNZ82_INVRT_DATA *axis, double *dTemp); <br />
bool GetPoweronTime( LNZ82_INVRT_DATA *axis, double *dTemp); <br />
bool GetOperatingTime( LNZ82_INVRT_DATA *axis, double *dTemp); <br />
<br />
};<br />
Scott Dolan
Jernie Corporation
Engineering & Manufacturing
Software, Hardware, & Enclosures
|
|
|
|
|
At this point we are having a communication breakdown. I sugggest you take a fresh look at your design. statements like: "I want mainloop to inherit ClxThread. but i also need it to inherit a Poll_Invertors." indicate that you are experiencing myopia. Step away from that thinking completely and try to see a different approach.
led mike
|
|
|
|
|
ScotDolan wrote: the mainloop class inherits,
ClxThread object, and Poll_LenzeInvertors object. The Poll_LenzesInvertors objects also inherits ClxThread object.
Not a good idea. This is known as the diamond multiple inheritance[^] problem and is usually indicative of a design problem.
led mike
|
|
|
|
|
Is there any Network based API Call to determine whether a machine exists on a network, a bit like what the '_access' call does for files?
|
|
|
|
|
Not sure, but I would guess there is, have you checked the Network API Documentation?
led mike
|
|
|
|
|
Thanks Mike!
Gonna use NetWkstaGetInfo()
|
|
|
|
|
rw104 wrote: Is there any Network based API Call to determine whether a machine exists on a network...
Will IsDestinationReachable() work for you? If not, how about NetServerGetInfo() or NetWkstaGetInfo() ?
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
Sounds good thanks!!!
|
|
|
|
|
I am trying to write a simple GDI program that displays a countdown timer(MM:SS:hh). I am just using the WM_PAINT message to display the updated time and calling InvalidateRect() in my main loop. This however causes the screen to flash as I am clearing the screen before I redraw the text.
FillRect(hdc, &rPos, (HBRUSH)GetStockObject(BLACK_BRUSH));
DrawText(hdc, stTime, stTime.GetLength(), &rPos, DT_CENTER | DT_WORDBREAK); Any suggestions on how I can stop the text from flashing while still being able to update at hundreths of a second?
Thanks, Dustin
|
|
|
|
|
InvalidateRect with the last [bErase] parameter FALSE. This will prevent from flickering.
If you will have a problem with the messed drawings (caused by previous drawings) you could use non-transparent mode or somth else like drawing a new background before the actual text is drawn [which I could see is done by your FillRect call].
--
=====
Arman
|
|
|
|
|
I had actually been using InvalidatRect with bErase set to false. The problem was that I was using transparent mode as you stated, and not seting the background of the text like Mark suggested.
Thanks for the help, Dustin
|
|
|
|
|
Now you are doing right.
The problem was that I was using transparent mode as you stated
Well, I said use 'non-transparent'
--
=====
Arman
|
|
|
|
|
Instead of drawing the background and drawing the text in two steps, try doing it in one:
::SetTextColor(hdc, RGB(0xFF,0xFF,0xFF));
::SetBkColor(hdc, RGB(0x00,0x00,0x00));
::DrawText(hdc, stTime, stTime.GetLength(), &rPos, DT_CENTER | DT_WORDBREAK);
You'll also want to follow Arman's advice so the background doesn't get repainted every update.
Also, WM_PAINT isn't the only place you can draw on the window from. You can draw the text from
anywhere you want. WM_PAINT messages are low priority so if you need better performance do
the DrawText from elsewhere. If it's from a different thread, you need to sync acess to the
HDC as always.
*edit* (Thanks Michael Dunn)
You'll still need to redraw the window contents in response to WM_PAINT and/or
WM_ERASEBKGND so the window is refreshed when it needs updating (e.g when another window is
dragged across it and/or off it).
*end edit*
Mark
-- modified at 14:21 Monday 14th May, 2007
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
Thanks for the halp Mark, that worked perfectly. I've become so dependent on DirectX I've forgotten how to use GDI properly.
Dustin
|
|
|
|
|
Mark Salsbery wrote: Also, WM_PAINT isn't the only place you can draw on the window from. You can draw the text from anywhere you want.
This is true, but if you do any drawing outside of WM_ERASEBKGND and WM_PAINT , you'll need to manually redo the drawing if the window becomes uncovered. (This is what causes people to ask "I draw something in WM_INITDIALOG but it goes away if I move another window over mine.") If you do all drawing in response to those two messages, you won't need to do that bookkeeping.
|
|
|
|
|
Yes. I should have included that in my response.
Thanks Mike!
Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
Hello, I have an Xml and I want to put data from it in tables how can I do this ...please if you have an idea of example or something like this..help me...thanks
|
|
|
|
|