I have two functions in a namespace (InstallPage), the second
function that I execute "unzip" makes the program window not respond
for a short period of time (about 10 seconds).
I've tried using threads and pools but I couldn't pass variables to
them, how could I execute these functions without blocking the
windows events?
Oh thank you so much, I was passing the variables wrong earlier as
you have shown me.
I was doing it like this earlier - thread::send -async
$download_thread {"download $location $version $status_list_box"}
Shaun Kulesa <shaunkulesa@gmail.com> wrote:
I have two functions in a namespace (InstallPage), the second
function that I execute "unzip" makes the program window not respond
for a short period of time (about 10 seconds).
I've tried using threads and pools but I couldn't pass variables to
them, how could I execute these functions without blocking the
windows events?
Threads are your best bet, and you pass variables to threads either as
a parameter to the 'thread::send' command, or by using the tsv (thread
shared variables) to pass the data.
For a simple unzip, simply passing the variable contents as parameters
of thread::send is easiest.
Otherwise you will have to write your own unzip that performs the work
of unzipping in small chunks, while allowing the event loop to run in
between each small chunk of work.
Say you had a thread who's handle is in $tid, and inside it has an
'unzip' proc that takes the same parameters as your code example.
You'd call the unzip in the thread from your main code like so:
thread::send $tid [list unzip $location $version $status_list_box]
Look up the -async option if you want to actually launch this 'in the background'. The above version will be synchronous with your code, but
I think the event loop will still be allowed to run (test it yourself
and see).
I have two functions in a namespace (InstallPage), the second function that I execute "unzip" makes the program window not respond for a short period of time (about 10 seconds).
I've tried using threads and pools but I couldn't pass variables to them, how could I execute these functions without blocking the windows events?
I would appreciate code as well as manual pages as I have been using manual pages but I cannot seem to get the code right.
```tcl
proc install {version filelocation} {
set version [get_version]
set location [get_location]
set status_list_box [listbox .install_frame.status_list_box -width 80 -height 10]
grid $status_list_box -row 2 -column 0 -columnspan 2 -sticky news
$status_list_box insert end "Downloading Tcl $version in $location"
download $location $version $status_list_box
unzip $location $version $status_list_box
}
proc download {location version status_list_box} {
set f [open "$location\\Tcl.zip" wb]
set tok [http::geturl $version -channel $f -binary 1]
close $f
if {[http::status $tok] eq "ok" && [http::ncode $tok] == 200} {
$status_list_box insert end "Downloaded successfully"
}
http::cleanup $tok
}
proc unzip {location version status_list_box} {
$status_list_box insert end "Installing Tcl $version in $location"
::zipfile::decode::open $location\\Tcl.zip
$status_list_box insert end "Extracting files to $location"
set archiveDict [::zipfile::decode::archive]
::zipfile::decode::unzip $archiveDict $location
::zipfile::decode::close
$status_list_box insert end "Installed successfully"
}
```
On 4/19/2023 11:03 AM, Shaun Kulesa wrote:
I don't have a return message as I can't currently get that to work as it will vwait for the return variable but if I print it then it will say it cannot find the variable.
The code below will get to "puts $download_return" and give the error:
Error:
can't read "download_return": no such variable
while executing
"puts $download_return"
Code:
set download_thread [thread::create {
proc download {location version status_list_box} {
return message "Downloaded successfully"
}
thread::wait
}]
thread::send -async $download_thread [list download $location $version $status_list_box] download_return
vwait download_return
puts $download_return
as shown,
return message "Downloaded successfully"
should fail
I don't have a return message as I can't currently get that to work as it will vwait for the return variable but if I print it then it will say it cannot find the variable.
The code below will get to "puts $download_return" and give the error:
Error:
can't read "download_return": no such variable
while executing
"puts $download_return"
Code:
set download_thread [thread::create {
proc download {location version status_list_box} {
return message "Downloaded successfully"
}
thread::wait
}]
thread::send -async $download_thread [list download $location $version $status_list_box] download_return
vwait download_return
puts $download_return
I have two functions in a namespace (InstallPage), the second function that I execute "unzip" makes the program window not respond for a short period of time (about 10 seconds).
I've tried using threads and pools but I couldn't pass variables to them, how could I execute these functions without blocking the windows events?
I would appreciate code as well as manual pages as I have been using manual pages but I cannot seem to get the code right.
It works now, I should take breaks when coding, I must have done something silly which caused an error.
When I said - "It works now, I should take breaks when coding, I must have done something silly which caused an error.", that was when I just tested it in the global code execution area. If I have it in my namespace it won't find the variable.
When I put $download_return on that last line, it won't find the variable, this only happens when I have it in a namespace.
namespace eval InstallPage {
namespace import ::VersionPage::*
namespace import ::LocationPage::*
proc create_gui {} {
...
}
proc install {version filelocation} {
set version [get_version]
set location [get_location]
set status_list_box [listbox .install_frame.status_list_box -width 80 -height 10]
grid $status_list_box -row 2 -column 0 -columnspan 2 -sticky news
$status_list_box insert end "Downloading Tcl $version in $location"
set download_thread [thread::create {
proc download {location version status_list_box} {
return "Downloaded successfully"
}
thread::wait
}]
thread::send -async $download_thread [list download $location $version $status_list_box] download_return
vwait download_return
puts $download_return
I'll try it your way... I need to fully understand it first.
I'm not sure what the $mainid is, are you creating a thread inside another thread and passing information from the child thread to the parent thread?
And if you doing that, what portion of the code is in the parent thread?
I'll try it your way... I need to fully understand it first.
I'm not sure what the $mainid is,
are you creating a thread inside another thread and passing
information from the child thread to the parent thread?
And if you doing that, what portion of the code is in the parent
thread?
The undefined variable $tid is what is confusing me.
The undefined variable $tid is what is confusing me.
When I tried unzipping a large zip file it made the program not respond, I must of done something wrong.
If I make the command and arguments a list:
thread::send $mainid -async [list $status_list_box insert end "Downloaded successfully"]
It will not insert the message into the list box.
If I make the command and arguments a list:
thread::send $mainid -async [list $status_list_box insert end "Downloaded successfully"]
It will not insert the message into the list box.
I fixed it by putting the version number on the end:I'm not familiar with the distro you are using (bawt) but I do know that a new thread does not always have everything the main thread has. For example, when I use the magicsplat distro, and I want to use Tk in a thread, even though I startup with wish,
package require http 2.9.8
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 498 |
Nodes: | 16 (2 / 14) |
Uptime: | 03:40:24 |
Calls: | 9,821 |
Calls today: | 9 |
Files: | 13,757 |
Messages: | 6,190,389 |