Some help with TThread (Terminate, FreeOnTerminate and other adventures in the realm of threading)
I'm trying the achieve the following (using Delphi7): After logging in to my program, the user gains control, but in the background a separate thread downloads a file from the Internet to check if the current license key is blacklisted. If it is, the user receives a prompt and the program terminates.
So I've created a separate TThread class which downloads the blacklist from the Net using InternetOpenURL/InternetReadFile.
My problem is the following:
If the user quits my program before the downloading in the background finishes, the license manager thread should be terminated by the main thread.
If the thread has done its job, it should terminate automatically.
If I use FreeOnTerminate := true I can't terminate the thread from the Main thread. But otherwise, how can I make the thread free its resources after it has done its job?
My other question is:
If the license key is blacklisted, I use Synchroni开发者_JS百科ze to do something with certain resources of the Application's main form.
But how do I know if the user has already closed the app and the program is in FormDestroy of the main form, for example? If I Synchronize in the wrong time, it could lead to access violations...
Thanks!
First, in your check thread object, create a "completed" flag. You can check this is true to determine if all is well. As Chris T suggests, have the thread set a global to indicate things are good/bad, so that the main thread can use something like a timer to check that and that all is well or take appropriate action.
Then, if your app wants to quit early, call
MyThread.Terminate;
MyThread.WaitFor;
And in the thread, check for Terminated being set at appropriate points. This way you can close down nicely.
For the second question, don't bother updating the UI from the thread. Just set a global flag. i.e. IsBlackListed := true; Now you can use that global flag as the basis for nagging the user, in response to some user-initiated action. Such as OnFileSave... ShowMessage('I would love to save that file for you, but unfortunately, you are using a blacklisted key.');
IsBlackListed Redux....
// globally...
var
IsBlackListed : integer;
...
initialization
IsBlackListed := 0;
...
// in your thread:
if OhMyGodThisIsABlackListedKey then
IsBlackListed := 1;
... Back in the main code, maybe in the OnSaveMyData event:
if IsBlackListed then
begin
IsBlackListed := -1; // so we don't repeat ourselves
MessageBox('Hey, you naughty pirate!');
MyDBConnection.Whatever.DoSQL('insert into licensetable (name,key) values(pirate,blacklisted);
end;
I think this is what you're trying to do.... Assign an OnTerminate() event to the TThread, which gets excuted as part of your main thread when the worker thread is terminated. You can do all of your UI updates there (the black listing). Make a property of your worker thread such as 'DownloadComplete', and only do the blacklisting/validating if thats set to true in the OnTerminated event. That should allow the thread to free itself regardless of the state of the download when the program runs, as long as you .watifor() it before the program exits.
精彩评论