ProcessMessages and use of application - delphi

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.

Related

Is there a way to do TThread.Synchronize with Timeout?

Sometimes you need to call TThread.Synchronize, but also you can enter in a deadlock situation.
For example:
Thread1.execute
procedure
begin
....
TThread.Synchronize(..)
...
end;
Then from the main thread doing something like:
Thread1.terminate;
Thread1.waitfor;
can leave to some deadlock because TThread.Synchronize will never succeed :(
I would like to know the most easy way to handle such scenario.
There is no way to use TThread.Synchronize() with a timeout.
You can use TThread.Queue() instead, passing it a procedure associated with a TEvent that you can wait on after Queue() exits. Then the main thread can signal that TEvent when it processes the request (just be sure to not free the TEvent until after the main thread has used it, unless you call TThread.RemoveQueuedEvents() to cancel the request first).
That being said, what you describe is NOT a deadlock scenario. If TThread.WaitFor() is called in the main UI thread, it processes pending Synchronize()/Queue() requests while waiting for the thread to terminate. If TThread.WaitFor() is called in another thread, then the main UI thread is free to process Synchronize()/Queue() requests normally.

How to be notified for time changes in Windows Service

I created a WindowProc to be notified for system time changes:
constructor TJJWScheduler.Create;
begin
fTimeChangeWnd := Classes.AllocateHWnd(TimeChangeWndProc);
end;
procedure TJJWScheduler.TimeChangeWndProc(var msg: TMessage);
var
i: integer;
begin
case msg.Msg of
WM_TIMECHANGE:
begin
// my things
end;
end;
end;
This code is running inside a Windows Service.
The problem is that it isn't fired when I change the system time!
Why not the broadcast message (WM_TIMECHANGE) isn't delivered to my window?
There is another way to do this without a loop?
EDIT
I don't known why, but I hardcoded the PeekMessage to process messages to that window, and everything comes to work fine. The code below solved my problem:
var
msg: TMsg;
if PeekMessage(msg, fTimeChangeWnd, WM_TIMECHANGE, WM_TIMECHANGE, PM_REMOVE) then
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
This workaround is very strange, because I already have others windows processing messages (by generic ProcessMessages), only this one isn't processing its messages.
The reason your window was not receiving the WM_TIMECHANGE messages is that your window is created from a secondary thread.
Each thread in a process has its own message queue. Synchronous messages are delivered when you service the message queue, so ever for a non-queued message like WM_TIMECHANGE you do need to service the secondary threads message queue in order for messages to be delivered.
For example, look at the documentation for GetMessage, the most common way to pull messages of the queue:
The function dispatches incoming sent messages until a posted message is available for retrieval.
The same is true for PeekMessage. It dispatches incoming sent messages before peeking the queue.
There are a handful of other ways for sent messages to be dispatched, but these are the primary ones.
Now, I suspect that it may be inconvenient for you to periodically dispatch messages from your secondary thread. If your secondary thread does nothing else then it can simply sit in the traditional GetMessage, TranslateMessage, DispatchMessage loop. And most of the time it will happily block in GetMessage dispatching any incoming sent messages. But if your secondary thread does more work then that's probably not a viable option.
You are already running and servicing a message queue on the main service thread. It may make more sense to make your listener window have affinity with the main service thread. Do that by creating it from code that runs in the main service thread.
Note also that AllocateHWnd is documented not to be thread-safe. You must not call it from any thread other than the main thread of the process. So, if you do wish to remain on a secondary thread, you'll need to use CreateWindow rather than AllocateHWnd. But this is perhaps yet another good reason to move this window onto the main thread.

how to get the information that did when thread is paused

how can i get actions ,i did when my thread is paused after resumed (Sorry for my bad english )
ok i will explain with code
function mythreadf(p:Pointer):DWORD stdcall;
var i:Integer;
begin
for i:=0 to 1000000 do begin
if myevent.WaitFor(INFINITE)=wrsignaled
then
begin
if Form1.RadioButton1.Checked then ShowMessage('Checked');
Form1.Label1.Caption:=IntToStr(i);
end;
end;
end;
i am pausing and resuming my thread using resetevent and setevent
after i paused my thread by clicking resetevent button and then i checked radiobotton1 after that when resume my thread by using setevent again .dont send error occuring and applications closing :(
can any one help me in this issue
regards
Edit 1:
Error image
http://i49.tinypic.com/11r7nkn.jpg
Accessing VCL UI controls directly in a worker thread is NOT thread-safe (even ShowMessage() is not thread-safe. Use the Win32 API MessageBox() directly instead). All kinds of bad things can happen, including crashes. You must delegate your UI access to the main thread instead. The TThread class has a Synchronize() method for that purpose. Or you can use any other inter-thread synchronization of your choosing, such as by using SendMessage() to send custom messages to a hidden window created in the main thread via AllocateHWnd() or CreateWindow/Ex().
Your thread, as Remy says, should not be accessing the checkbox. Also it's bad programming style. Your background thread has a purpose? That purpose will help you find a name. If you create a class that inherits from TThread, you will get farther, faster.
interface
type
TMyElephantCountingThread = class(TThread)
protected
FResultStr:String; // holds something for later display on the user interface
FOptionChecked:Boolean; // set from main thread, to tell background thread whether or not a checkbox option is checked.
....
end;
....
implementation
....
function TMyElephantCountingThread.ElephantCounterResults;
begin
// all data fields in here is local to this thread
if FOptionChecked then
FResultStr := IntToStr(FIntegerValue);
end;
As you can see my code above uses only fields that belong to my thread object.
If FOptionChecked needs to be set equal to the value of Checkbox.checked, that must be done in the main thread.
You can not copy and paste write code from your foreground thread (which can access your VCL objects) into your background thread code (which can not safely access those objects), and not expect problems.

TThread.resume is deprecated in Delphi-2010 what should be used in place?

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.

Get window to refresh (etc) without calling Application.ProcessMessages?

I've got a legacy app here that has a few 'time-consuming' loops that get fired off as a result of various user interaction. The time-consuming code periodically updates something on the screen with progress information (typically a label) and then, seemingly to persuade the visual refresh to happen there-and-then, the code calls Application.ProcessMessages (argh!).
We all know now what kind of trouble this can introduce to a GUI app (being charitable, it was a more innocent time back then) and we're finding that sure as eggs, from time to time we get users achieving the impossible with the program because they're clicking on controls while the program is 'busy'.
What's the best way of periodically refreshing the visuals of the form without taking-on other events/messages etc?
My thoughts were to either;
- disable all of the controls before doing anything time-consuming, and leaving the '...ProcessMessages' calls in place to 'force' the refresh, or
- find another way to refresh a control periodically
I can do the former but it left me wondering - is there a better solution?
example code from legacy;
i:=0;
while FJobToBeDone do
begin
DoStepOfLoop;
inc(i);
if i mod 100 = 0 then
begin
UpdateLabelsEtc;
Application.ProcessMessages;
end;
end;
I can already hear you all fainting, at the back. :-)
If you call Update() on the controls after you have changed properties you will force them to redraw. Another way is to call Repaint() instead of Refresh(), which implies a call to Update().
You may need to call Update() on parent controls or frames as well, but this could allow you to eliminate the ProcessMessages() call completely.
The solution I use for long updates is by doing the calculations in a separate thread. That way, the main thread stays very responsive. Once the thread is done, it sends a Windows message to the main thread, indicating the main thread can process the results.
This has some other, severe drawbacks though. First of all, while the other thread is active, you'll have to disable a few controls because they might restart the thread again.
A second drawback is that your code needs to become thread-safe. This can be a real challenge sometimes. If you're working with legacy code, it's very likely that your code won't be thread-safe.
Finally, multi-threaded code is harder to debug and should be done by experienced developers.
But the big advantage of multi-threading is that your application stays responsive and the user can just continue to do some other things until the thread is done. Basically, you're translating a synchronous method into an asynchronous function. And the thread can fire several messages indicating certain controls to refresh their own data, which would be updated immediately, on the fly. (And at the moment when you want them to be updated.)
I've used this technique myself quite a few times, because I think it's much better. (But also more complex.)
Do not call Application.Processmessages, This is slow and might generate unlimited recursion.
For example, to update everything in Panel1 without flick, we can use this method:
procedure TForm1.ForceRepaint;
var
Cache: TBitmap;
DC: HDC;
begin
Cache := TBitmap.Create;
Cache.SetSize(Panel1.Width, Panel1.Height);
Cache.Canvas.Lock;
DC := GetDC(Panel1.Handle);
try
Panel1.PaintTo(Cache.Canvas.Handle, 0, 0);
BitBlt(DC, 0, 0, Panel1.Width, Panel1.Height, Cache.Canvas.Handle, 0, 0, SRCCOPY);
finally
ReleaseDC(Panel1.Handle, DC);
Cache.Canvas.Unlock;
Cache.Free;
end;
end;
For better performance, the cache bitmap should be created at first and free when the process has finished
The technique you're looking for is called threading. It is a diffucult technique in programming. The code should be handled with care, because it is harder to debug. Whether you go with threading or not, you should definitely disable the controls that users should not mess with (I mean the controls that can effect the ongoing process). You should consider using actions to enable/disable buttons etc...
Rather than disable the controls, we have a boolean var in the form FBusy, then simply check this when the user presses a button, we introduced it for the exact reasons you mention, users clicking buttons while they wait for long running code to run (it scary how familiar your code sample is).
So you end up with something like
procedure OnClick(Sender:TObejct);
begin
if (FBusy) then
begin
ShowMessage('Wait for it!!');
Exit;
end
else FBusy := True;
try
//long running code
finally
FBusy := False;
end;
end;
Its impotent to remember to rap the long running code up in a try-finally block in case of exits or exception, as you would end up with a form that will not work.
As suggested we do use threads if its for code that will not affect the data, say running a report or data analysis, but some things this is not an options, say if we are updating 20,000 product records, then we don't want anyone trying to sell or other wise altering the records mid flight, so we have to block the application until it is done.

Resources