I used this tutorial http://delphi.about.com/od/kbthread/a/thread-gui.htm to create a class that asynchronously downloads a file from the internet in another thread with a TDownLoadURL
. I did this because I want to download a file without blocking the UI thread so the program doesn't become unresponsive during large downloads, the progress bar can update, etc.
I am having a problem because even though I have done the download in another thread (inheriting from TThread and doing the work in the Execute method) the GUI thread seems to be blocked and does not process messages until the download is finished. Here is the code for my class: http://codepad.org/nArfOPJK (it's just 99 lines, a simple class). I am executing it by this, in the event handler for a button click:
var
frame: TTProgressFrame;
dlt: TDownloadThread;
begin
dlt := TDownloadThread.Create(True);
dlt.SetFile('C:\ohayo.zip');
dlt.SetURL('http://download.thinkbroadband.com/512MB.zip');
dlt.SetFrame(frame);
dlt.SetApp(Application);
dlt.Start;
Note: The SetApp method was for when I was manually calling app.ProcessMessages
from inside the UpdateDownloadProgress
method of my class TDownloadThread
. This would keep the GUI from being unresponsive, but it made the progress bar behave wierdly (the moving glowing light thing of aero's progress bar moving way too fast), so I removed it. I want to fix this properly, and if I have to call ProcessMessages
there's really no point in multithreading it.
Can someone help me fix this problem? Thanks.
Graphical user interfaces often have a dedicated thread (“GUI thread”) for servicing user interactions. The thread must remain responsive to user requests even while the application has long computations running. For example, the user might want to press a “cancel” button to stop the long running computation.
Threads in a process run independently of each other. One thread blocking shouldn't necessarily block the other threads. This is one of the main reasons that threads are used in the first place,.
When we say that a thread blocks, we mean that the method (operation) that the thread calls, put or take, is blocking the thread from proceeding to execute the next line of code until some condition is met — the queue is not full or queue is not empty.
To keep your application responsive, it is essential to avoid using the main thread to perform any operation that may end up keeping it blocked. Network operations and database calls, as well as loading of certain components, are common examples of operations that one should avoid in the main thread.
I now have the solution for you!
Calling TDownLoadURL.Execute
(your call to dl.Execute
in TDownloadThread
) results in the action being transferred back into the main thread which is why your UI becomes unresponsive.
Instead you should call ExecuteTarget(nil)
which performs no such machinations and works as you intend: the download runs on the worker thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With