delphiindyindy10delphi-11-alexandria

Why does an Exception thrown in a thread screw up my UI?


I use a TThread to send emails using Indy. It works great, and by using a separate thread, I avoid my apps UI freezing while TIdSMTP sends.

The problem is, if an exception occurs during sending, a lot of weird things start to happen in my app's UI.

For instance, I have a TPanel on the bottom used to show the current status. I feed this panel in every sending step, using events like TIdSMTP.OnConnected and TIdSMTP.OnDisconnected, for instance.

If an exception occur during sending, like for instance, 'Socket error', new updates to Panel.Caption 'mix' with prior panel captions, like this:

image

Also, my app's whole UI gets really screwed up, and the only way to fix it is to close the app and reopen it.

Looks like I'm doing something wrong in my thread exception handling, but I use threads a lot for other procedures and this issue happens only when I use TIdSMTP.

Is there something I need to do on TIdSMTP to avoid this weird behaviour?


Solution

  • You should never be accessing UI components directly from any of your secondary threads. Doing so usually leads to race condition between your application code and Windows GUI system.

    In best cases this would lead to visual glitches like the one you encountered. But in worst cases it could lead to instability or even crash of the whole windows UI.

    So the correct way for accessing any UI elements is from your application main thread. In order to do so easily Delphi provides two methods:

    1. Synchronize which forces for your code to be executed in main thread. It also suspends execution of the current thread while the method executes in the main thread.
    2. Queue Unlike Synchronize, execution of the current thread is allowed to continue. The main thread will eventually process all queued methods.