As you can tell, I am having a little trouble with the TTimer VCL component within my application developed using Delphi 2010.
Whenever I call:
Self.Timer1.Enabled := False;
Self.Timer1.Enabled := True;
The timer component does seem to indeed halt, but, it never starts up again. Like, it never calls the OnTimer event.
I am using it in conjunction with the Indy10 IRC component (TIdIRC).
Thanks in advance :)
You are also aware that most Indy calls are blocking? A timer works by sending Windows Messages which means the messages need to be processed in order for the timer to fire. If the application/main thread blocks it does not process messages and timers do not get fired. Maybe this is your problem?
Also if your application is a Windows Service or a console application the messages might not be processed.
Take Indy out of the equation and see if you can get it to basically throw up the hint every 10 seconds. If not, you're doing something wrong. Like mis-interpreting the interval time. For instance, "(10000/10 seconds)" is not very clear. I think you mean "10000ms which is 10 seconds" but you don't show your code, so I can only guess. Delphi won't guess, it will do what you tell it.
Anyway, make a sample app with a form, button, edit box and a ttimer and experiment. Get the timer stuff working, before you introduce the Indy stuff. Then you know whether you've got a TTimer problem or an Indy problem.
You must make sure that you call these methods of TTimer only in the context of the main thread. Since Indy uses threads it may well be the case that this rule is violated. To find out easily you can call Assert when the code is executed in the context of another thread:
Assert(GetCurrentThreadId = MainThreadId);
Self.Timer1.Enabled := False;
Self.Timer1.Enabled := True;
I don't know what Self is referring to in your code, but it's worth trying.
I created a Timer in a separate thread and everything is working well again :)
Thanks guys, I learned a lot of stuff.
Related
I am using TTimer in my software and it supposed to run forever 24/7. Nowhere in my software is that timer disabled or stopped from running. It's main function is to update table's value. It is started as soon as the software is run and from that point on TTimer should not stop. However, after running for over a month, that TTimer mysteriously stops running. The software is run on Windows 7 and the software is developed on Delphi 2010 XE. I've searched my code to see what might be causing it, but I can't figure out what.
Timer1.Enabled:=true;
That's how the timer is started.
UPDATE:
After doing some investigation, I found out that the TTimer never stopped, but there is another issue. My TStringGrid table on a TForm just simply don't show any values being updated. Further, I also found out that my TList List I am using to store list of data item is being destroyed somehow that the list becomes empty. But the data items in the list are not deleted anywhere in the code once they are loaded only when the program is started.
Everytime I update the TStringGrid on the form, I run through my TList items from 0 to count-1 location. So, if there is no item in the TList in the memory, my code simply skips
over the display part and thus nothing gets updated on the TStringGrid.
Something like:
If (List.count>0) then
begin
//Display values in TStringGrid;
end;
But while the software is still running, I was able to reload my list of items from a file
back into TList list and my software started to work like it supposed.
I hate to say the ugliest word programmers hate the most. I am afraid I may have a memory leak. Anyone think so?
Any help will be greatly appreciated. Thanks.
I bet it stops 49 days after reboot. When Windows GetTickCount wraps around. Sure you're not doing a check that would fail based on this?
TTimer is just a wrapper around the Windows SetTimer() API which I believe will run forever.
I suspect that the timer still runs, but the event handler that it fires is failing to operate as desired.
I'm not sure why it's stopping after a month; I'd suspect (as Erik said) you have something using GetTickCount() that's failing after the wraparound at ~49 days.
As a general rule, though, it's better to stop/start the timer to prevent a delay from causing a timer message to be dropped:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
try
// Do whatever on timer event firing
finally
Timer1.Enabled := True;
end;
end;
You might try this instead of just allowing it to run constantly; if it is a bug in the TTimer code (I don't see anything after a quick scan of XE's TTimer implementation), stopping and starting may reset things to prevent the failure.
You should free memory allocated after the job is done:
Timer1.FreeOnRelease() or .Free();
I want to download a file from internet and I imagine this should be a simple task. Trying several different approaches I have found that each one has its own drawback.
The main issues are:
Application freezes until it downloads the file
Application freezes forever if the Internet connection is lost/server does not respond.
(details:
How to retrieve a file from Internet via HTTP?
The connection does not timeout while downloading file from internet )
So, finally I used the suggestions I got from several people to use "pro" libraries such as Indy. However, Indy is not much better than the pieces of code I have tried (but it is way much larger and difficult to maintain). While using Indy the application does not freezes only for short periods so it is still (somehow) usable. However, the application cannot be shut down until the download finishes (never if the Internet connections gets broken).
Other people reported the same problem: http://borland.newsgroups.archived.at/public.delphi.internet.winsock/200609/0609079112.html
https://forums.embarcadero.com/thread.jspa?threadID=25199&tstart=90
So, there is some hacking I had to do to TIDAntiFreeze in order to make it work?
Also, the ConnectTimeout property is not recognized.
fIDHTTP := TIDHTTP.Create(NIL);
fIDHTTP.ConnectTimeout:=5000;
Should I drop Indy and return to original idea of downloading the file in a separate thread and end the thread when it does not respond (at least this way I get rid of 3rd party libraries)? There will be unforeseen side effects if I do this?
Using: Delphi 7, Indy 10.1.5 10.5 (probably).
Thanks
You probably need to use Indy the Indy way: using threads. Indy was specifically designed to work in blocking mode, because that's how most internet protocols work (example: with HTTP, at protocol level, you send a request, then you read the response. You don't send and receive at the same time). TIdAntiFreeze is supposed to help you use some Indy functionality without dealing with threads; I never used that because, at least conceptually, it's an ugly hack.
If you don't want to deal with threads then you should take a look at ICS - it was designed to be used in async mode, without threading. It doesn't need the equivalent of TIdAntiFreeze because it's not blocking. You start a download and you handle some events to get progress and completion notifications. ICS is just as well-known, professional and wildly used as Indy.
It's not too difficult to solve these sorts of problems. The first thing you have to do is make sure that you have properly handled error handling. If something fails then make sure everything cleans up properly. Beyond that make sure the downloading code is part of a separate thread. If there is any problem you can always terminate the thread from your main program. Here's the code (for downloading only, not the threading) which is working fine for me.
with TDownloadURL.Create(nil) do
try
URL := 'myurltodownload.com';
filename := 'locationtosaveto';
try
ExecuteTarget(nil);
except
result := false;
end;
if not FileExists(filename) then
result := false;
finally
clear;
free;
end;
I'm using the Multimedia timer in Delphi and this works great for quite accurate callbacks (compared to a traditional TTimer). However the callback is from another thread. I dont have a convenient form to use for PostMessage() or a message based means of notifying my app that the callback has happened - I just have a class. I'm happy with a message based solution (if necessary). What is the easiest way of sending some kind of event from the Windows callback into my class?
THanks
Brian
The standard solution is to create an invisible window using AllocateHWnd procedure as a field of your class to receive messages sent from callback function. A nice usage example of AllocateHWnd procedure is TTimer component.
I want to detect when a file date changes and update a DevX TdxMemData which is used as a Tdatasource which then would be seen in a TDBGrid that uses it.
I've found some code that uses ReadDirectoryChangesW, but seems rather complex for my simple needs.
I'm considering using a TTimer and firing it off every five seconds. (That's fine enough accuracy for me.)
Are there any caveats in doing this? I've read that Threads have all sorts of restrictions on VCL access, etc. Does the same thing apply to TTimer events?
Is there anything I need to watch out for when calling FileAge and updating a DevEx TdxMemData object while in a Timer event? Will those updates be seen by my main app?
Is there a way to detect the "state" of my program when a Timer event gets control so I can avoid problems?
Or am I opening an enormous can of worms in thinking about using a TTimer for this?
TTimer events are called within the main application thread, so there's no problems with accessing VCL objects from them. It's called when your application is idle, so it won't take place while your in an OnClick handler or anything similar unless you manually call Application.ProcessMessages.
I'd suggest using ReadDirectoryChangesW though. If you use a timer you will continue polling even if the application is idle and the file isn't changing. It will keep your CPU from going idle and keep could keep the hard drive from spinning down, which can have negative effects for power saving and battery usage.
In Demos directory there's "ShellChangeNotifier" component, which will fire events when files get modified, added or deleted inside directory. However it has only one OnChange event, so you don't know what really happened.
There's some discussion and solution about the issue in about.com
Windows lets you monitor file changes. As a jump start see http://delphi.about.com/od/kbwinshell/l/aa030403a.htm. There are several ready made components available, too. Google for "delphi monitor file change" or something similar
You can check my: DirectoryWatch
It is a wrapper around "ReadDirectoryChangesW" functions. It is more specific about changes than "ShellChangeNotifier".
my delphi 2009 app uses a DLL that performs some activities that may take several seconds. i'd like to show a progress bar. unfortunately the DLL call is a blocking call & has no callback function.
a way i've been considering is to add a TTimer to my app. when the timer event fires, i look at the time and use that to calculate the progress % and update the progress bar.
i did that, would i have problems with the fact that the VCL is not thread safe?
thank you!
I don't know much about Delphi but if it runs on windows , you might need to do this.
1) Because your user interface is not thread safe, you need to PostMessage into the user-interface thread to update the progress bar.
2) If your user-interface thread is the thread calling into the DLL, then you wont be pumping messages, so you cant update your user-interface. You could call MsgWaitForMultipleObjectsEx to continue pumping messages while waiting, but since the wait is within the DLL , you dont have a handle to wait for. Is it possible to move your call into the DLL to another thread ? Then you can wait on that thread handle. This way your progress bar will continue to operate.
I dont know much about Delphi, but my colleagues tell me it runs Win32 based function calls, so it operates very much like a windows program on windows.
Since the DLL is blocking, you need to call it from a secondary worker thread. If you call it in the main thread, your TTimer will be blocked and thus unable to update the UI.