-2

If an user provides information that is recorded in an excel file then I choose Excel COM to read the data. However, as the user can repeat the process to N files and the process can take a while, I decided to move this routines to a separated thread.

Therefore, I need your advice to define how can I do this.

The worker thread cannot be destroyed until there is no more remaining files. Inside the thread the data is loaded to a ClientDataSet and at the end is applied to database.

I need somehow notify the user when task is done, so he can decide if he will load another file and execute the thread again or finish the job.

How to properly destroy the thread and notify the user?

EProgrammerNotFound
  • 2,403
  • 4
  • 28
  • 59
  • Calling Execute method of TWorker thread is a serious bug: your code is still executed in context of a main thread. You have to call Start method instead. – pf1957 Jul 12 '13 at 21:15
  • What are you asking here? – David Heffernan Jul 12 '13 at 21:41
  • 1. There is no OnFinish and you already found OnTerminate. 2. That depends. – David Heffernan Jul 12 '13 at 22:05
  • Don't wait for it. Get it to send the main form a message when it is done. – David Heffernan Jul 12 '13 at 22:09
  • Don't `WaitForSingleObject`. Disable the menu item or button that allowed the user to start the process, assign a handler to the thread's `OnTerminate` event then `Start` the thread. When it's done, the event you assigned to `OnTerminate` will be called, and you can notify the user from there that the thread is finished and make the menu item or button available again. You shouldn't be waiting for the thread; if you are, it defeats the whole purpose of using a thread in the first place. (Your post asks far too many questions. There are lots of posts here about threading; do some research.) – Ken White Jul 12 '13 at 22:29
  • This site is not for "centralizing all of the questions you have and asking for documentation all at once". Ask one (or possibly two, if they're closely related) questions per post, so that they can be answered. If you ask four or five separate questions, individual answers can be posted for each one, and no single answer could be chosen as correct. Read the [help] pages about asking questions here; it clearly explains the "one question/one answer" concept. This is not a "Please write a book to answer all my questions about this topic" site. :-) – Ken White Jul 12 '13 at 22:41

1 Answers1

7

Should I create and destroy the thread to each file?

You can, but that is not a very efficient design. Put the files into a thread-safe queue, then start the thread if it is not already running, and then have the thread loop through the queue util it is empty. At that time, the thread can then be destroyed, or just put to sleep in case more files will be queued later on.

This design also allows you to process multiple files in parallel if you implement a thread pool. When you put a file into the queue, start a new thread if there is not already an idle thread waiting to be used. When a thread starts, pull the next available file from the queue. When that thread finishes, it can pull the next file from the queue, and if there is no file then go back into the pool for later reuse.

If so, How to properly destroy the thread and notify the user?

When you are ready to destroy a thread, call its Terminate() method (its Execute() needs to should check its Terminated property periodically and exit when set to true), then call its WaitFor() method (or equivalent, like MsgWaitForMultipleOjects(), which allows you to keep the message queue responsive while waiting for the thread to terminate), then free it from memory. The thread triggers its OnTerminate event after Execute() exits, however it is not safe to destroy the thread in the OnTerminate event handler. If you want to destroy the thread when the OnTerminate event is triggered (especially if you are not expecting the thread to terminate, such as if it threw an uncaught exception), you can post yourself an asynchronous notification, such as with PostMessage(), PostThreadMessage(), TThread.Queue(), etc, and then destroy the thread when that notification is processed at a later time.

How to set a thread to notify the user when the work is finished? By assigning the event OnTerminate?

Yes. Unless the thread is going to process multiple files before terminating, in which case the thread could manually send a notification in between each file.

It's better to create the thread to each file or create 1 thread and somehow control it's execution to every time for different files?

Creating and destroying a thread is not trivial for the OS, in terms of resources and processing, so you should re-use threads as much as possible. Make them sleep when they have nothing to do, unless they are going to be sleeping for a long time in which case you should destroy them to release their resources.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770