TCL 线程:跟踪子 Tcl 线程仍然 运行
TCL Thread: Tracking that a child Tcl Thread is still running
我遇到了确定 Tcl 线程是否仍然 运行 的问题。我的代码如下所示:
package require Thread
proc p1 {} {
set tid [thread::create {
#Child Thread
proc executeCommand {} {
#Run several command line commands
return 1
}
thread::wait
}]
set currentProcessID [twapi::get_current_process_id]
set var ::p1results($tid)
set $var ""
#Get all threads before ::thread::send
set beforeThreads [twapi::get_process_thread_ids $currentProcessID]
::thread::send -async $tid [list executeCommand {}] $var
#Get all threads after ::thread::send
set afterThreads [twapi::get_process_thread_ids $currentProcessID]
#set processThreadId to be the difference between before and after twapi calls
set processThreadId {}
foreach threadId $afterThreads {
if {[lsearch -exact $beforeThreads $threadId] == -1} {
set processThreadId $threadId
}
}
while {[lsearch -exact [twapi::get_process_thread_ids $currentProcessID] $processThreadId] > -1} {
#Notify a database that child thread is still running
after 3000
}
vwait $var
set result [set $var]
unset $var
::thread::release $tid
return $result
}
p1
如您所见,我目前正在跟踪子线程,它是从 ::thread::send 开始的,使用的是 TCL twapi 包。我不想用 'vwait' 阻塞父线程,否则我将无法通知 DB 子线程仍然是 运行。这已被证明是不可靠的,因为偶尔我存储的线程 ID 'processThreadId' 会在我的线程 'proc executeCommand {}' 完成之前退出。
所以我的问题是 - 是否有一种可靠的方法让父线程(主线程)跟踪子线程是否仍然 运行,而不用 'vwait' 阻塞父线程?
如果你有工作线程的id,你可以使用thread::exists
查询它是否还活着。它只需要 id 作为参数,returns 一个布尔值,这应该正是你所需要的。
但是,线程可能会在您提出问题后立即死亡;在真正的通用异步系统中没有办法阻止这种情况。我更喜欢安排工作线程在完成后发回一条消息,一旦收到该消息,我就知道一切都已完成。我经常喜欢考虑将 "work items" 发送到线程,而不仅仅是简单的消息。
我使用 thread::mutex 锁解决了这个问题,它比我之前使用的 twapi 包可靠得多。
本质上,我创建一个thread::mutex并在父线程中获取锁。然后我 thread::send 到我的工作线程互斥句柄。然后父线程循环,尝试重新锁定互斥锁和 catching/ignoring "locking the same exclusive mutex twice from the same thread" 错误消息。当"thread::mutex lock"不抛出错误时,父线程会跳出while循环。
工作线程遍历其命令列表并在 return 语句之前调用 "thread::mutex unlock"。我还需要将 "executeCommand" 包装在 catch 语句中,以便在工作线程出现意外错误时解锁互斥体。
所以被锁定的互斥体代表工作线程 运行ning,一旦它被解锁,它就没有更多的命令到 运行。
package require Thread
proc p1 {} {
set mutexHand [::thread::mutex create]
set tid [thread::create {
proc wrapCommad {mutHand} {
if {[catch {set data [executeCommand]} err]} {
thread::mutex unlock $mutHand
return -code error $err
}
thread::mutex unlock $mutHand
return $data
}
proc executeCommand {} {
#Run several command line commands
return 1
}
thread::wait
}]
set var ::p1results($tid)
set $var ""
thread::mutex lock $mutexHand
::thread::send -async $tid [list wrapCommand $mutexHand] $var
while {1} {
if {[catch {thread::mutex lock $mutexHand} err] } {
puts "WORKER STILL RUNNING"
} else {
puts "WORKER NOT RUNNING"
break;
}
after 3000
}
vwait $var
thread::mutex unlock $mutexHand
thread::mutex destroy $mutexHand
set result [set $var]
unset $var
::thread::release $tid
return $result
}
p1
我遇到了确定 Tcl 线程是否仍然 运行 的问题。我的代码如下所示:
package require Thread
proc p1 {} {
set tid [thread::create {
#Child Thread
proc executeCommand {} {
#Run several command line commands
return 1
}
thread::wait
}]
set currentProcessID [twapi::get_current_process_id]
set var ::p1results($tid)
set $var ""
#Get all threads before ::thread::send
set beforeThreads [twapi::get_process_thread_ids $currentProcessID]
::thread::send -async $tid [list executeCommand {}] $var
#Get all threads after ::thread::send
set afterThreads [twapi::get_process_thread_ids $currentProcessID]
#set processThreadId to be the difference between before and after twapi calls
set processThreadId {}
foreach threadId $afterThreads {
if {[lsearch -exact $beforeThreads $threadId] == -1} {
set processThreadId $threadId
}
}
while {[lsearch -exact [twapi::get_process_thread_ids $currentProcessID] $processThreadId] > -1} {
#Notify a database that child thread is still running
after 3000
}
vwait $var
set result [set $var]
unset $var
::thread::release $tid
return $result
}
p1
如您所见,我目前正在跟踪子线程,它是从 ::thread::send 开始的,使用的是 TCL twapi 包。我不想用 'vwait' 阻塞父线程,否则我将无法通知 DB 子线程仍然是 运行。这已被证明是不可靠的,因为偶尔我存储的线程 ID 'processThreadId' 会在我的线程 'proc executeCommand {}' 完成之前退出。
所以我的问题是 - 是否有一种可靠的方法让父线程(主线程)跟踪子线程是否仍然 运行,而不用 'vwait' 阻塞父线程?
如果你有工作线程的id,你可以使用thread::exists
查询它是否还活着。它只需要 id 作为参数,returns 一个布尔值,这应该正是你所需要的。
但是,线程可能会在您提出问题后立即死亡;在真正的通用异步系统中没有办法阻止这种情况。我更喜欢安排工作线程在完成后发回一条消息,一旦收到该消息,我就知道一切都已完成。我经常喜欢考虑将 "work items" 发送到线程,而不仅仅是简单的消息。
我使用 thread::mutex 锁解决了这个问题,它比我之前使用的 twapi 包可靠得多。
本质上,我创建一个thread::mutex并在父线程中获取锁。然后我 thread::send 到我的工作线程互斥句柄。然后父线程循环,尝试重新锁定互斥锁和 catching/ignoring "locking the same exclusive mutex twice from the same thread" 错误消息。当"thread::mutex lock"不抛出错误时,父线程会跳出while循环。
工作线程遍历其命令列表并在 return 语句之前调用 "thread::mutex unlock"。我还需要将 "executeCommand" 包装在 catch 语句中,以便在工作线程出现意外错误时解锁互斥体。
所以被锁定的互斥体代表工作线程 运行ning,一旦它被解锁,它就没有更多的命令到 运行。
package require Thread
proc p1 {} {
set mutexHand [::thread::mutex create]
set tid [thread::create {
proc wrapCommad {mutHand} {
if {[catch {set data [executeCommand]} err]} {
thread::mutex unlock $mutHand
return -code error $err
}
thread::mutex unlock $mutHand
return $data
}
proc executeCommand {} {
#Run several command line commands
return 1
}
thread::wait
}]
set var ::p1results($tid)
set $var ""
thread::mutex lock $mutexHand
::thread::send -async $tid [list wrapCommand $mutexHand] $var
while {1} {
if {[catch {thread::mutex lock $mutexHand} err] } {
puts "WORKER STILL RUNNING"
} else {
puts "WORKER NOT RUNNING"
break;
}
after 3000
}
vwait $var
thread::mutex unlock $mutexHand
thread::mutex destroy $mutexHand
set result [set $var]
unset $var
::thread::release $tid
return $result
}
p1