TCL:超时一个可能挂起的过程

时间:2016-01-22 08:16:17

标签: timeout tcl

我创建了一个可能会根据输入挂起的过程。现在我想为它设置一个超时值并强制它返回并在时间结束后继续其他工作。

vwait方式似乎不适用于我的情况。如果我在我的proc之后放vwait,例如:

after sometime set status timeout
proc_may_hang
vwait status

如果proc挂起,vwait将永远不会执行,事件循环永远不会启动,系统也不知道监视变量状态。

我也不能使用多线程来启动监控过程。 TCL解释器来自EDA软件,Thread包不可用。

那么无论如何都要强迫proc返回?非常感谢!

1 个答案:

答案 0 :(得分:0)

线程可以提供帮助,但需要一些连线。这是一个杀死长期运行线程的线程示例。

package require Thread

# Create a thread with needed procs for calculation.=.

proc spawn {} {
    set t_id [thread::create {

        # Source your program here.
        # Make sure to have thread::release when calculation is final.
        # source myfile.tcl

        # this is an example proc
        proc do_calculation {params} {
            # add this to your program
            # get your params for calculation from item
            foreach {parent_id callback index item} $params {}

            set i 10000

            while {$i > 0} {
                incr i $item
                if {$i > 99999} {
                    set i 10000
                }
            }

            # Run something when calculation is done here...
            puts "All done! i = $i"

            # Or in the parent thread in item_complete 
            thread::send -async $parent_id [list $callback $index $item]
            thread::release
        }

        # Don't change beleow. The thread::wait keeps the thread running
        # so can send it a command.
        thread::wait
    }]
}

proc check_thread {t_id seconds callback {started 0}} {

    # If the thread doesn't exist then it probably finished and called thread::release.
    if {[thread::exists $t_id] == 0} {
        $callback
        return
    }

    # Check the time remaining for the thread to complete.
    set now [clock seconds]

    if {$started == 0} {
        set started $now
    }

    set seconds_remaining [expr {$seconds - ($now - $started)}]

    puts "$seconds_remaining seconds remaining."

    # Stop the thread if it took too long.
    if {$seconds_remaining < 1} {
        puts "Times up... stopping thread `$t_id`."
        thread::release $t_id
        $callback
        return
    }

    # Check the thread again in 1 second.
    after 1000 [list check_thread $t_id $seconds $callback $started]
}

# some fake data. Package your data into a list of items to process.
set items [list 1 -1 9 -9 20 -20]
set items_i 0

proc next_item {} {
    global items
    global items_i

    if {$items_i < [llength $items]} {
        set item [lindex $items $items_i]
        incr items_i
        set t_id [spawn]
            # Tell the thread to run the calculation.
            thread::send -async $t_id [list do_calculation [list [thread::id] item_complete $items_i $item]]
        check_thread $t_id 10 next_item 
    } else {
        puts "Items completed. exiting."
        exit
    }   
}

proc item_complete {index item} {
    puts "Item #${index} completed successfully. Item = ${item}."
}

next_item

vwait forever