|
|
I have found the error:I can't end the thread after destorying the window,right?
|
|
|
|
|
Chen-XuNuo wrote: I can't end the thread after destorying the window,right?
Right Not if the thread is using the window!
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I am going to be crazy..
The problem still haven't been solved.
UINT BulletGo(LPVOID pParam)
{
CBullet* bullet=(CBullet*)pParam;
while(TRUE)
{
switch(bullet->GetDirection())
{
case UP:
bullet->GoUp();
break;
case DOWN:
bullet->GoDown();
break;
case LEFT:
bullet->GoLeft();
break;
case RIGHT:
bullet->GoRight();
break;
}
if(!bullet->m_bCanGo)
break;
else
bullet->MoveWindow(bullet->GetPosition().x,bullet->GetPosition().y,
bullet->GetThisRect().Height(),bullet->GetThisRect().Width());
Sleep(30);
}
return 0;
}
BOOL CBullet::GoDown()
{
if(m_rtParent.bottom==0)
GetParent()->GetClientRect(&m_rtParent);
if((m_ptPosition.y+m_rtThis.Height())<m_rtParent.bottom)
{
m_ptPosition.y+=6;
m_bCanGo=TRUE;
return TRUE;
}
else
{
m_bCreated=FALSE;
m_bCanGo=FALSE;
while( ::WaitForSingleObject(m_pThread->m_hThread,1) == WAIT_TIMEOUT)
{
Sleep(1);
}
delete m_pThread;
this->DestroyWindow();
return FALSE;
}
}
I destroy the window after ending the thread.
Is the judgement:
::WaitForSingleObject(m_pThread-&gt;m_hThread,1) == WAIT_TIMEOUT
right?If it is right,where is the problem..
|
|
|
|
|
Chen-XuNuo wrote: ::WaitForSingleObject(m_pThread->m_hThread,1) == WAIT_TIMEOUT
That should work fine, although you really don't need to loop.
A simple
::WaitForSingleObject(m_pThread->m_hThread, INFINITE);
should be good enough.
Chen-XuNuo wrote: delete m_pThread;
This isn't good. CWinThread objects delete themselves by default.
If you delete it twice, whichever delete happens last is going to crash!
You probably should remove that line
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Thank you very much.The problem has been solved.
|
|
|
|
|
If you want my advice, I don't think that you need to create a thread for that. If you keep that logic, it would mean that you will create a thread for every bullet in your game. And probably for every ennemy too. Honnestly, I don't think this is a good idea.
You should better process the position of all your 'entities' (bullets, ennemies, ...) in the message pump and then draw everything on the screen. You don't need a thread for that.
I don't know if you are using the MFC's or not, but if that's the case, then you won't have access to the message pump. But you could override the OnIdle function from your App class and do it there.
|
|
|
|
|
OnIdle...bleh. I'd prefer a multimedia timer for smoother frame rate
Cheers
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mmmm...I think if I draw the 'entities' with DC,I think the application would take large CPU resource,so I do it in thread.And I think using thread to control the enemies and the bullets easier.
I will try you advice, thank you~
|
|
|
|
|
I am exporting two functions. Cleanup and close.
extern "C" __declspec(dllexport) BOOL Cleanup(VOID)
and
extern "C" __declspec(dllexport) BOOL Close(VOID)
In the Cleanup function i am calling Close() method.
if ( temp.lpLocalData->hComm != INVALID_HANDLE_VALUE ) {
Close();
}
This resulted in two compiler error
error C3861: 'Close': identifier not found and
error C2365: 'Close' : redefinition; previous definition was 'formerly unknown identifier'
How to call Close in Cleanup function?
|
|
|
|
|
It should work. If you don't provide prototypes beforehand,
then Close() will have to be defined before Cleanup() so the
compiler knows what it is...
extern "C" __declspec(dllexport) BOOL Close(VOID)
{
return TRUE;
}
extern "C" __declspec(dllexport) BOOL Cleanup(VOID)
{
Close();
return TRUE;
}
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
|
Hello everyone,
I am debugging MSDN code from,
http://msdn2.microsoft.com/en-us/library/0eestyah(VS.80).aspx
here is my output,
1<main.cpp>
1<d:\visual studio="" 2008\projects\test_c4350\test_c4350\main.cpp(21)="" :="" warning="" c4350:="" behavior="" change:="B::B(A)" called="" instead="" of="B::B(B&)">
1> d:\visual studio 2008\projects\test_c4350\test_c4350\main.cpp(13) : see declaration of 'B::B'
1> d:\visual studio 2008\projects\test_c4350\test_c4350\main.cpp(9) : see declaration of 'B::B'
1> A non-const reference may only be bound to an lvalue
I do not quite understand why there is a warning A non-const reference may only be bound to an lvalue and 'B::B(A)' called instead of 'B::B(B &)'? Could anyone give some descriptions please?
thanks in advance,
George</d:\visual></main.cpp>
|
|
|
|
|
I can't be bothered to go looking at that code, but...
Of course the left value of an assignment has to be non-const.
Otherwise...
7 = a;
The compiler / interpreter will work out the right hand side (which may or may not be const), and then put it into the left hand side. If the left hand side is not "put into-able", then it will fail.
Does that help halfway?
Iain.
|
|
|
|
|
Iain Clarke wrote: Does that help halfway?
why bothering replying ?
you're answer will not be understood, therefore you're probably be down voted for this good answer though.
|
|
|
|
|
I'm a glutton for punishment!
I hope the light at the end of the tunnel isn't a train.
Iain.
|
|
|
|
|
lol. come on, take my hand
|
|
|
|
|
Iain Clarke wrote: I hope the light at the end of the tunnel isn't a train.
Greetings.
--------
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
“The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson
|
|
|
|
|
Thanks Iain,
My question is, why a non-const reference can not binded to a rvalue?
I think the reason is rvalue is not addressable? And we can not change the rvalue through its reference? Are there any other reasons? I am not quite sure whether my understanding is fully correct. Since there are some
non-modifiable lvalues (so we do not always need to modify values
through its reference). I am still studying what is the reason in
essence in compiler why a non-const reference can not be binded to a
rvalue.
Please feel free to correct me if I am wrong.
have a good weekend,
George
|
|
|
|
|
I know what they're on about now, having read the page you point to.
In short, for those (like me) who don;t want to slog through too much work to help someone...
class A
{
...
};
class B
{
public:
B ( A &a );
B ( const A &a);
....
};
...is the example MS use.
As it a warning, and one you have to explicitly enable. So microsoft are labelling using a non-const reference as inadvisable, not a failure.
This non-const reference rule applies to more than constructors. Imagine operator= members, which can be mutated into copy constructors.
void MyFunction (CBigClass &big)
{
COtherClass other;
other = big;
other.DoStuff ();
}
So far so good? big is a big class, involving connecting to databases on construction, etc. You don't want to make new ones, so you pass it by reference or reference. But you don't want the bugs that come by passing by pointer. What if some evil person passed me a NULL? So you pass by reference.
The above function looks pretty innocuous? You would think nothing of using...
CBigClass b;
b.Blah ();
MyFunction (b);
Now imagine...
class COtherClass
{
....
COtherClass &operator=(CBigClass &b);
....
};
COtherClass &COtherClass::operator=(CBigClass b)
{
....
b.DoSomethingNotConst ();
....
return *this;
}
Suddenly, you have a bug that doesn't manifest until much later, and would be really hard to track down. After all, you're just using =! Where's the harm in that?
And if you say
"But Iain! I'm the mighty George! So mighty, I was called George twice! I would never use a bad member function of a class I'm supposed to just be copying! Nevermind my addiction to exclamation points!!!", then I would say...
"In that case, what's the harm in declaring the = function as
COtherClass &operator=(CBigClass const &b);
after all, you weren't going to anything non-const, were you?"
Most of the time, when things have to be one way, just ask yourself, what if they didn't? You can usually find something bad that would happen.
Here endeth the lesson, from the gospel according to Iain. My fingers are now tired.
Iain.
|
|
|
|
|
Thanks Iain,
Is there a typo in your code?
The declaration of assignment operator is (input parameter is reference type),
COtherClass &operator=(CBigClass &b);
But the implementation is (input parameter is object type, not reference type)
COtherClass &COtherClass::operator=(CBigClass b)
regards,
George
|
|
|
|
|
|
Hi Iain,
This is what you mentioned in your long post,
Iain Clarke wrote: Suddenly, you have a bug that doesn't manifest until much later, and would be really hard to track down.
I have re-read your code, but I can not see any bugs. It is appreciated if you could point out.
If you mean the input parameter should be defined as non-const reference, I do not think it is a bug, it is a design and function limitation.
regards,
George
|
|
|
|
|
The bug is the DoSomethingNotConst () being called in the operator = function, and the compiler not telling you off, because you hadn't consted the reference(s) in the operator= function.
In the following snippet
Class C a,b;
b.FillWithValues ();
a = b;
you would expect a = b to not change b at all.
And if you write the copy constructor using a const reference, then it is harder to mess up and make that mistake. That's all. The const keyword just makes it that bit harder for you to mess up.
If you're a super programmer who never makes mistakes, and remembers the reason for every line of code you've ever written, then you never need the const keyword at all.
Guess what. You're not that super programmer. Neither am I.
const is like a sports cup. It makes it that bit harder to have a nasty injury.
Iain.
|
|
|
|
|
Thanks Iain,
My question is answered. You are a super developer whose thoughts are not easily caught.
regards,
George
|
|
|
|