• Re: GUI is non-responsive during a long database interaction

    From Rich@21:1/5 to Alan Grunwald on Thu Mar 6 19:52:23 2025
    Alan Grunwald <nospam.nurdglaw@gmail.com> wrote:
    In the meantime, I tried to execute the database interaction in a
    separate thread (?) by running it as an [after idle] script but this
    didn't have the desired effect

    An after idle script is not a "separate thread", as you've now
    discovered.

    For real threads, use the 'thread' extension:

    https://www.tcl-lang.org/man/tcl/ThreadCmd/thread.htm

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et99@21:1/5 to Alan Grunwald on Thu Mar 6 13:38:55 2025
    On 3/6/2025 9:42 AM, Alan Grunwald wrote:
    Hi. The subject says it all really.

    -snip-

    Is there any way to achieve what I'm trying to do, short of using the full threads package, which I've never used before and would like not to have to get to grips with right now.

    -snip-

    Using Tcl Threads can be rather easy - if you know which 95% of the threads manual pages to ignore. The man pages are not meant as a tutorial, and for that, I would recommend Ashok's tcl book.

    However, your problem is trivially solved with a second thread. You simply want to run your query in the second thread and have it send back the result to a global variable which you then vwait on. Using vwait allows your gui to remain responsive.

    First off, your program and it's gui already runs in a thread, it's called the main thread. Every tcl program begins in the main thread. You only need to create a second thread:

    The structure of your second thread might be thus:

    package require Thread

    set thread_script {
    package requires...
    ... other init code if any ...
    proc query args {
    ....
    return $result
    }
    thread::wait
    }

    To use this to create the second thread:

    set tid [thread::create $thread_script]

    The variable tid is the thread id you will use below to send the thread some work to do.

    Then to do a query:

    thread::send -async $tid [list query arg1 arg2 ... ] ::result
    vwait ::result

    The above sends the query to the thread "tid" which calls the proc and returns the result in the global variable ::result (this variable ::result gets set in the main thread, not the second thread).

    You could do something between these two statements, but to just keep the gui going that's not required. You might need some sync code however, so any gui callbacks don't occur before a required result from the query. But that's another topic.

    Note: Each thread runs in a separate interpreter, so each thread gets its own (private) set of global variables.

    For example, you might want to include an init proc as well, and it could just store such things as the data base handle in a global variable where the query proc could use it later. Of course you could also use namespaces, but they're not really needed
    inside such a simple thread as above.

    You also can ignore the tpool package, as it's not needed if you do it as in the above layout.

    If you can come up with a small example of using your database, in a self contained small example, i.e. one that can be copy/pasted into a tcl console for example, then I suspect many here could easily give you a threaded version that would require
    probably no more than 10-15 lines of additional (thread) code.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ted Nolan @21:1/5 to rich@example.invalid on Thu Mar 6 21:15:54 2025
    In article <vqcudn$346r4$1@dont-email.me>, Rich <rich@example.invalid> wrote: >Alan Grunwald <nospam.nurdglaw@gmail.com> wrote:
    In the meantime, I tried to execute the database interaction in a
    separate thread (?) by running it as an [after idle] script but this
    didn't have the desired effect

    An after idle script is not a "separate thread", as you've now
    discovered.

    For real threads, use the 'thread' extension:

    https://www.tcl-lang.org/man/tcl/ThreadCmd/thread.htm


    Alternately you could send the queries to a seperate process
    connected by a pipe and use I/O fileevents to keep your main process
    from blocking.
    --
    columbiaclosings.com
    What's not in Columbia anymore..

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)