A separate thread creates a TidTCPClient and a TTimer. The TTimer is set to 3s and if the TCPClient is not connected, it calls TCPClient.Connect.
If there is no server to connect to, this results in an attempt to connect every 3 seconds.
The main thread (UI) does nothing, but if I grab the window with the mouse and move it slowly across the screen, it get's stuck every 3 seconds for about 2 seconds, then it jumps to the mouse-cursor position and follows the mouse again, until the next attempt to connect occurs.
In other words, the main thread seems to be blocked when the TCPClient tries to connect.
Why does this happen, even though the TCPClient is in it's separate thread?
Your TTimer works by receiving WM_TIMER messages; Those messages are dispatched using the VCL's main message pump, in the VCL threads. After the 3 seconds expire your TTimer.OnTimer event runs in the main thread, so the call to Connect runs in the main VCL thread.
You get blocked because you're not threading!
Related
I use Delphi 10.2 Tokyo with Indy (the integrated version).
Scenario:
I do http GET requests (TIdHttp) in threads, and use proxies.
Sometimes, a proxy seems to cause Indy not to timeout, and not to return from a GET.
I also assign the onWork event handler to react to an Abort button and call within this handler the idHttp.Disconnect function. When the GET seems to be frozen, the abort also does not work, possible that in this case the onWork event is not triggered, I have no idea.
The main thread is idle and only create lets say 50 threads, each does a GET via its instance of TIdHttp. Ans sometiumes, as I mentioend, a proxy cause of GET not to return which result then in a "hanging" thread.
My question is: How can I force Indy to abort, from an external thread? Is there anything what can be done via code when the GET refuse to return?
I solved my issues by using a background thread to disconnect sockets and implement a timeout, which seems to work even socket are "frozen" and the onWork is not triggered.
I do this by adding the TIdHttp instances I create to an array, together with the time the instance was created. If the GET return normal, the array entry will be removed. In a background thread, I check if the user clicked Abort, and then loop through the array and call disconnect on each instance. I also check in the same thread if a timeout period was reached, and also call disconnect.
Might not be the perfect solution, but it works for me.
Hi I have been asked to maintain a Delphi 5 based program for someone, and the program is using a timer object to tick every 50 milli-seconds and upon each time-up it runs the block of single threaded code. I am just wondering, what would happen if the time taken to execute this block of code is longer than the timer tick interval, would this be bad? For example could it cause problems like access violation? How does Delphi handle this kind of situation by default? Thanks a lot.
The critical part of this question is :
... what would happen if the time taken to execute this block of code is longer than the timer tick interval, would this be bad?
It's not great, but it's not a show stopper and it certainly cannot cause access violations. Delphi's TTimer is implemented using the WinAPI SetTimer function.
You might naively think that if your timer's handler took longer than the interval to process that the timer would continue to pile up messages in the message queue and your program would effectively lock up with a flood of timer messages that had no hope of ever all being processed. Thankfully, this isn't exactly how timers work. The documentation can shed some light.
WM_TIMER message
The WM_TIMER message is a low-priority message. The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue.
Now, there isn't really a concept of "high" and "low" priority messages in a windows application, and while this statement is a little ambiguous we can take the context to mean that WM_TIMER is a message that is not posted to the application's message queue but rather generated in response to a GetMessage or PeekMessage call when a timer has been set with SetTimer, when that timer's interval has elapsed, and when there are no other messages already in the queue.
So, while the timer interval may elapse during your handler's processing, any other messages that come in while this is happening will still enter the queue normally and will be processed once your handler completes. Only once the queue has been emptied again will another WM_TIMER message be generated.
The timer events, therefore, will execute either at the rate of the tick interval or as fast as your application can process them, whichever ends up being longest. If you do have timer messages coming in too quickly, however, and your timer handler's processing time is long then your application's responsiveness can suffer. It won't become unresponsive, but all other message processing will be restricted to being processed at the interval of your timer's event handler execution time. This can make your application feel sluggish.
Example
To demonstrate, create a new forms application and add a TTimer component with an interval set to 10. Then attach this handler :
procedure TForm1.Timer1Timer(Sender: TObject);
begin
sleep(200);
end;
While the program is running, try moving the window around. What we have done is to essentially quantize the application's message processing to a 200ms interval (the duration of the timer's event handler execution).
Ticks of the timer do not interrupt your code.
Timer ticks are delivered in the form of window messages. Window messages can only arrive when you check the message queue for new messages. That happens automatically when your timer event handler returns and your program resumes its event loop, but you can trigger it explicitly by calling Application.ProcessMessages. Don't call that, though; it seldom solves problems in the long run.
If you don't check the message queue in your timer-tick handler, then your handler will never start running a second time while it's still handling a previous tick.
Even if you do check the queue, all that happens is that the tick handler will be called recursively. After all, it's all running in a single thread. Recursive timer handling probably isn't what you want to happen, though, so I'll again counsel against checking for messages in a message handler.
Furthermore, timer messages can never "pile up" if your timer handler takes a long time to run. Timer messages are "fake" in that they don't actually get added to the message queue at regular intervals. Instead, the OS will synthesize a timer message at the time your program checks the queue for more messages. If there are no higher-priority messages in the queue, and the timer interval has elapsed, then the OS will return a wm_Timer message. If you don't check for more messages, then there will be no timer message in the queue. In particular, there will not be multiple timer messages in the queue.
Further reading:
Stack Overflow: How does the message queue work in Win32?
Dr. Dobbs: Inside the Windows Messaging System
I have an app which creates a thread which communicate with the main UI via windows messages. It simply send the message to the main app thread and received the status.
That way I am displaying modal windows and do other things.
The problem is when I have to display a form which makes a call to a com+ server.
That way I get OLE error 8001010D: An outgoing call cannot be made since the application is dispatching an input synchronous call.
I think it happens because primary SendMessage is in use and com+ calls need windows messaging for its tasks.
Anyway, In delphi I cannot display the form from a thread, but how Could I workaround the problem ... ?
Thanks
EDIT:
MAIN(UI) 2. A THREAD
A. A Thread(2) sends message to a main thread (1)
B. Main thread(1) receives the msg and before letting it come back to a thread
it displays the window.
C. The modal window in main thread wants to make a com+ call, the above error occurs.
What thread the modal window is in? 2. Which thread the COM call goes from? 3. Which thread the COM object was instantiated in? 4. Is the background thread initialized with an STA? 5. Is the modal form being shown from a SendMessage handler? – Roman R. 2 mins ago
MAIN
MAIN
MAIN
CoInitializeEx(nil, COINIT_MULTITHREADED);
yes.
The problem cause comes from inability of COM to marshal an outgoing COM call while processing SendMessage request. The error which comes up is RPC_E_CANTCALLOUT_ININPUTSYNCCALL (0x8001010D), which you are referring to. I was under impression that this only applies to SendMessage calls which are a part of incoming interthread COM requests, however this might have been a false assumption.
Your typical workaround would be to replace your SendMessage with PostMessage followed by waiting for synchronization object, event or semaphore. This way your caller background thread does not hold messaging to synchronize the calls and waits autonomously, on the main thread the message being dispatched through regular message queue and eventually reaches the same handler.
As a bonus, you have an option to safely terminate the background thread. If currently it's being locked by SendMessage API waiting for modal dialog, the suggested change would let you signal the synchronization object from the main thread and let it keep running, e.g. if you want to safely terminate it.
An alternate solution might be to call InSendMessage function and if true - defer modal UI, e.g. by again posting a message to self to pop the form up in another message handler later.
I have a TTimer in my application that fires every 2 seconds and calls my event handler, HandleTimerEvent(). The HandleTimerEvent() function modifies shared resources and can take 10's of seconds to execute before returning. Furthermore, I call Sleep() in the event handler to relinquish the processor at times.
I'm not sure how C++ builder's TTimer object works when it comes to calling events, so the scenario I just explained has got me thinking, particularly, whether HandleTimerEvent() gets called before a prior call has returned.
The question comes down to a couple of things.
Does the TTimer object queue the events?
Can the TTimer object call my event handler before a prior call has returned?
This reply assumes that TTimer is still implemented to use WM_Timer messages. If the implementation has changed (since 2005), please disregard.
No, the TTimer object does not queue events. It is driven by the Windows WM_Timer message, and Windows does not let WM_TIMER messages stack up in the message queue. If the next timer interval occurs and Windows sees that a WM_Timer message is already in the app's message queue, it does not add another WM_Timer messsage to the queue. (Same for WM_Paint, btw)
Yes, it is possible for a TTimer.OnTimer event to be fired even while a prior event handler is still executing. If you do anything in your event handler that allows the app to process messages, then your timer event can be reentered. The obvious one is if your event handler calls Application.ProcessMessages, but it can be much more subtle than that - if anything you call in your event handler internally calls Application.ProcessMessages, or calls PeekMessage/GetMessage + DispatchMessage, or opens a modal dialog, or calls a COM interface that is bound to an out-of-process COM object, then messages in your app message queue will be processed and that could include your next WM_Timer message.
A simple solution is to disable the timer object when you enter your timer event handler, and reenable it when you exit your timer event handler. This will prevent timer messages from firing while your event handler is still working, regardless of the message handling characteristics of your code.
I use TTimer extensively. It does not queue events. If you want it to hand off to an event handler, then create a TThread that handles your events so the Timer can continue with it's work. The timer does not operate asychronously but rather synchronously.
I am developing a project for BB. The application works with the network and sends / receives data via HTTP. Now I use the queue and queue manager. Manager starts with a background thread and works in while (true) loop, checking the queue for new transactions to the server. If the queue is not empty, then the transaction is executed, otherwise the manager goes to sleep for 200 ms.
The process of the transaction as follows:
- Runs another thread (using the Runnable), which opens a connection to the network and first thread waiting for background thread or timeout (and for that we need a loop), which we set.
- If the connection is established, then starts another thread (using the Runnable), which runs getResponseCode (), and first thread waiting for background thread or timeout (and for that we need a loop), which we set.
Before it, we showing popup window with wait-rotating-image, and after it is removed. It synchronized via Application.getEventLock ().
Iit unstable sometimes and thread sleeps for a long time ignore timeout-waiting-loop.
I would like to know how valid such an approach, what advice and best-practice is, what is your experience?
I use 4.5, 4.6, 4.7 and 5.0.
The lock returned by Application.getEventLock() should only be used for code that modifies the UI or UI components - it's the lock used by the event dispatcher. You should not be using it for background tasks such as HTTP processing. If you want to synchronize that code, it would be best to just create your own lock object.
You do not need that many threads, your EDT (event dispatch thread a.k.a main thread) should insert he job (some runnable class) into a queue and use wait/notify to inform a dedicated worker thread, that is responsible for network transaction, to check the queue.
The worker thread will be responsible for opening connection, writing to connection and reading from it.
For information about wait/notify mechanism check out:
A simple scenario using wait() and notify() in java
Due to the fact that you can't update the UI using the worker thread, Once the network transaction is completed you can update the UI layer using InvokeLater
For more details go to http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/Application.html#invokeLater(java.lang.Runnable)
you can set a timeout in the HTTPConnection itself, but if you don't want to rely on that mechanism, you can schedule a TimerTask that will execute after some time and handle the timeout in case no response is received.
Once the response is received all you need to do is cancel the TimerTask so that the timeout will not be triggered.
Check out http://www.blackberry.com/developers/docs/4.0api/java/util/TimerTask.html