Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operations in separate TThread block GUI thread

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.

like image 501
Kokonotsu Avatar asked Feb 19 '11 18:02

Kokonotsu


People also ask

What is GUI thread?

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.

Can threads block independently from one another?

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,.

What is a blocking thread?

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.

Why should we implement a separate thread to implement network operations?

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.


1 Answers

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.

like image 123
David Heffernan Avatar answered Sep 30 '22 05:09

David Heffernan