Click to See Complete Forum and Search --> : _beginthread problem


joe_pool_is
August 22nd, 2005, 12:40 PM
I have developed a class that updates our software when an update is detected on our FTP site. My objective is to make the interface as simple as possible so that other developers do not need to know anything about how threads work in order to use it. I have, therefore, designed a simple public method as follows:
int cFTP::FtpStart(bool bThread);
where bThread equal to false disables threading and true enables threading.

My class begins by FTPing into our company's server and downloading a small (~200 byte) text file containing the software upgrade version. If the upgrade is newer than what they are running, a MessageBox is displayed, asking permission to download it. (Updates could range from 3 - 20 MB, and our customers could have slow connections. So this update could potentially take a long time!)

As long as bThread is set to false, the class works. It is when I set this value to true that I experience problems, and it is certainly in the unique way that I have implemented _beginthread. I am hoping that someone will be able to see why my technique can not be used, and suggest ideas to fix it.

Here is the (greatly simplified) code:void kickOff(void* pObj)
{
((cFTP*)pObj)->FtpStart(false);
}

int cFTP::FtpStart(bool bThread)
{
if (bThread == true)
{
void* pObject;
pObject = (void*)this;
_beginthread(kickOff, 4096, pObject);
return 1;
}
// This section is always called
DownloadTextFile();
if (UpdateAvailable() == true)
{
if (MessageBox(NULL, "An update is available. Download it?",
"AutoUpdate", MB_YESNO) == IDNO)
{
return 0;
}
DownloadSetupFile();
}
return 0;
}
I was unable to pass my class method FtpStart to _beginthread, so I devised a "work around" by calling kickOff to do it for me. Apparently, I have created something that I was not supposed to, but I can not think of a better way of doing it. The compiler does not see any errors, but the program becomes non-responsive when the MessageBox returns IDYES (even an IDNO response causes no issues). I would certainly appreciate any help.

Regards,
Joe

MikeAThon
August 22nd, 2005, 09:28 PM
....I was unable to pass my class method FtpStart to _beginthread, so I devised a "work around" by calling kickOff to do it for me. Apparently, I have created something that I was not supposed to, but I can not think of a better way of doing it.
It's standard and ordinary to pass the "this" pointer to a thread as the thread's parameter. So, what you did is (in principle) just fine.

....The compiler does not see any errors, but the program becomes non-responsive when the MessageBox returns IDYES (even an IDNO response causes no issues). I would certainly appreciate any help.

It seems then that the problem resides in the DownloadSetupFile() function. What do you do there?

Also, are you certain that the cFTP object still exists by the time that the thread is executing? Here's what I mean:

Presumably, you are calling FtpStart( true ) from inside some function like "Initialize()". But if you do the following, then the cFTP object will no longer exist by the time the thread needs to access its DownloadSetupFile() function:
//.. pseudo-code
BOOL Application::Initialize()
{
cFTP ftp;
ftp.FtpStart( true ); // returns immediately after creating the thread
// .. other initialization
return TRUE;
}
// Note: the "ftp" object is now out of scope

If that's similar to your code, then the "ftp" object goes out of scope while the thread still needs to access it. Note that FtpStart() will return immediately after creating the thread, maybe before the thread has even begun to execute, and almost certainly before the thread is finished with the DownloadSetupFile() function and the cFTP object. You need some mechanism to make your chosen cFTP object persistent. Maybe a member variable...

Mike