Finding the timer thread is the issue. I have a parent object with a timer message copied out of TCustomGrid.
private
procedure WMTimer(var Msg: TWMTimer); message WM_TIMER; .....................................
Its parent is TWinControl. It calls TimerEvent(ID: Integer); virtual; in the protected part of my object. I override this in my descendant object and the procedure first contains Inherited; in it. I use a SetTimer(Handle, 1, 60, nil); in my create and in the procedure TimerEvent last uses KillTimer(Handle, 1); at the bottom. WMTimer fitted with a breakpoint, but will not stop the timer thread anywhere in my code. Also TimerEvent(ID: Integer); has a break point with same result everywhere. I have no problems with the object's handle as I'm using it for other things with no problems. Am I missing something like some hit call.
Finding the timer thread is the issue.
Timers do not create threads. The timer messages and callbacks are executed on the thread that called SetTimer.
Whatever your problem is, it's not related to the existence of a timer thread. If you want further help with the problem I suggest you post a new question with an MCVE.
At a wild guess, you could very well be subject to VCL window re-creation. The window handle that you pass when you create the timer has destroyed and re-created during the lifetime of the VCL control. This is very normal behaviour.
You should not use a VCL control's window handle in this way since the window is subject to re-creation. Instead use a bespoke window handle created with a call to AllocateHWnd. The point about windows created with AllocateHWnd is that you are in control of their lifetime.
I came across this piece of Delphi code while searching for background methods to execute tasks in firemonkey.
TThread.CreateAnonymousThread(
procedure()
begin
Sleep(10000);
TThread.Synchronize(TThread.CurrentThread,
procedure
begin
Button2.Text := 'OK';
end);
end).Start;
Is TThread.Synchronize at this case really necessary?
TButton.Text changes a property of a Window object, which is inherently non-thread-safe, and is only to be accessed directly from the thread which created it OR via message sends/posts.
What TThread.Synchronize does is - it wraps the procedure together with a waitable object, places this to a queue, and waits on the handle - it may post a message to the main thread to wake it up.
If the code behind TButton.Text was implemented via posted message - and is is not - it would be safe to call from other threads, but it would not take effect immediately.
Long story short - you definitely have to call this via Synchronize, for good reasons.
Is thread safe if a thread asynchronously read the information from VCL Controls in Delphi?
eg.
procedure TMyThread.Execute;
var bOK:Boolean;
iOK:Integer;
begin
while not terminated do
begin
bOk:=MyForm.cbCheckBox.Checked;
iOK:=MyForm.Left;
sleep(20);
end;
end;
If it is not thread safe how should I do to catch the event when the checkbox has changed its property.
No it is not safe. Your code is liable to lead to the window handle being created with affinity to the wrong thread.
Don't use the GUI to store your applications state. Use the GUI to show a view onto that state. Once you separate the state from the view you are home and dry. Your worker threads can use the underlying state state without touching GUI.
I need to know if use of ProcessMessages that allow me to use entire application is legal.
Pseudo code:
Main thread button call - search.
procedure ButtonOnClick;
begin
var1 = ExecuteSearch();
end;
function ExecuteSearch:Something;
begin
thread.StartThread;
while thread.Finished do
Application.ProcessMessages;
result := something;
end;
When I use this construction I can click other parts of my software and use it. But I don't know how this works. And if its safe.
Whilst this can be made safe, you are playing with fire. You run the risk of re-entrancy. You have to make sure that the user cannot press the button again. I trust you have disabled it whilst the search is running. You must make sure that it is disabled before you first call ProcessMessages.
My advice would always be to avoid using ProcessMessages. Better would be to start the thread and arrange for it to notify the main thread when it is done. Of course, you still need to disable the button whilst the thread is running.
However, if you really must use ProcessMessages don't do it with a busy loop like this. There's not much point using an entire processor to wait for a long running search operation to complete. Use a more intelligent blocking loop like this:
while MsgWaitForMultipleObjects(1, Thread.Handle, False,
INFINITE, QS_ALLEVENTS)=WAIT_OBJECT_0+1 do
Application.ProcessMessages;
The MsgWaitForMultipleObjects function will block until either:
A message is placed on the queue, or
The thread is signaled. The thread is signaled when it is complete.
The loop terminates when the thread is signaled, but also processes any queued messages.
Though the code is safe, what you could also do is use the OnTerminate event on the thread you're starting. This way you let Delphi control how to post back from the background thread to the main thread. Internally it uses the thread's Synchronize method, which you can use yourself to let the thread post intermediate progress information to the main thread.
In my multithread application
I use TThread.suspend and TThread.resume
Since moving my application to Delphi 2010 I get the following warring message
[DCC Warning] xxx.pas(277): W1000 Symbol ‘Resume’ is deprecated
If Resume is deprecated what should be used in place?
EDIT 1:
I use the Resume command to start the thread - as it is Created with 'CreateSuspended' set to True and Suspend before I terminate the thread.
EDIT 2:
Here is a link the delphi 2010 manual
Charles if do you read the code of TThread class , do you find the answer.
TThread = class
private type
..
..
..
public
constructor Create(CreateSuspended: Boolean);
destructor Destroy; override;
procedure AfterConstruction; override;
// This function is not intended to be used for thread synchronization.
procedure Resume; deprecated;
// Use Start after creating a suspended thread.
procedure Start;
// This function is not intended to be used for thread synchronization.
procedure Suspend; deprecated;
procedure Terminate;
See this link RAD Studio 2010: Community pulse: The day after. (Part 2)
Edit:
If you need to synchronize threads, you can use a scheme based on TMutex, TEvent and critical sections.
Bye.
Use TThread.Start instead of .Resume
--EDIT--
Start can of course only be used with Delphi 2010 (and later, presumably) to start a thread that was created suspended (where you would have used Resume before).
Using Resume/Suspend (or corresponding WinAPI functions) for thread synchronisation is NOT recommended. See the discussion here (have a look at Barry Kelly's comments).
Suspend and Resume were (or used to be) potentially broken in the TThread class (if you look at the source you will see that the Suspend method directly and unconditionally sets a Boolean to indicated thread suspended state rather than more robustly deriving this state from the execution count on the thread handle. Ironically the Resume method does use this more robust indicator to update the suspended state Boolean).
This is possibly why they have been deprecated. It's also why I implemented my own class to encapsulate a Windows thread with a more robust suspend and resume mechanism as well as the ability to Restart a thread once it had completed.
I'm not sure why their deprecation is supposedly related to synchronization. Suspending and resuming threads is not necessarily related to synchronization, although I can see how it might be. It's interesting to note that the equivalent methods in the .NET framework Thread class are similarly marked as obsoleted. And the same comments w.r.t synchronization appear in the Windows API documentation for thread suspend/resume.
If using deprecated methods makes you nervous and you still wish to suspend/resume you could always use the Windows API to suspend and resume the thread by reference to it's handle.
Just in case all you wanted to do was get rid of the compiler hints
(1) To get rid of the compiler hint when Starting a Thread ...
replace
MyThread := TMyThread.Create(True);
MyThread.Resume;
with
MyThread := TMyThread.Create(True);
MyThread.Start;
(2) To get rid of the compiler hint when Stopping a Thread ...
replace
MyThread.Suspend;
MyThread.Terminate;
with
MyThread.Terminate;
Not a big deal at all. Beware of attempted obfuscation.
Thread behavior control code should lie with in a thread procedure. Use appropriate sync objects and corresponding API calls in order to suspend/resume thread execution. Doing it from outside is a dangerous practice. So there was a decision to depricate it.
Use
Suspended := False; // Resume;
or
Start;
You should create the thread as follows:
constructor TSignalThread.Create;
begin
// create event handle first!
FEventHandle := CreateEvent(
{security} nil,
{bManualReset} true,
{bInitialState} false,
{name} nil);
FWaitTime := 10;
inherited Create({CreateSuspended}false);
end;
This way a call to Start is not required.
See http://www.gerixsoft.com/blog/delphi/creating-threads for an explanation why this code works.
#mghie (a little late, I know)
take for example madexcept and alike. If your application crashes and a bug report is being shown to user, that means that the dialog waits for use input. If it so happens that the crash is a result of a thread action (not necessarily a thread crashing), if you do not suspend the threads, the screen will be filled with bug report dialogs.
example 2: logging. for any particular reason, I at least, had the need to log some threads execution state. That includes the current stack trace. Now, as you (should) know, you cannot do that while the thread is running because during the time you collect information about it, the threads keeps doing stuff so by the time you finish collection, the information collected will not be consistent. Hence, you need to suspend the thread.
And I can go on with practical examples on thread management. Granted, these are not things you do in every day programming, but at least the first example I am sure that many of you are using, even if you are not aware of the internals of it. Debuggers? again, you use them.
But indeed, in all these cases, TThread is not used, since the work is done on thread handles. So, indeed, a valid example of TThread suspend usage is hard to come by. But threads in general, that's another story.