Предотвратить блокировку потока tcl основным циклом событий

Я пытаюсь запустить поток непрерывно и не блокировать его основным циклом событий tcl. Вот простой пример того, что я пытаюсь сделать:

#!/bin/sh
#\
exec tclsh "$0" "$@"

package require Thread

set ::a_thread [thread::create {thread::wait}]

proc start_a {} {
  thread::send $::a_thread {
    puts "Running a thread"
  }
  after 1000 a_start
}

proc infinite_loop {} {
  while {1} {
    puts "Loop"
    after 500
  }
}

start_a
infinite_loop

vwait forever

В этом коде вызывается процедура infinite_loop, и основной цикл событий выполняется бесконечно. Я бы хотел, чтобы a_thread все еще мог работать в фоновом режиме. Как я могу этого добиться?


person elmt    schedule 19.11.2010    source источник


Ответы (2)


Основной цикл событий не блокирует ваш поток. Вместо этого вы используете основной цикл обработки событий для планирования выполнения сценариев в потоке. Вместо этого запустите планировщик в самом потоке:

Код протестирован и работает должным образом:

thread::send $::a_thread {
    proc loop {} {
        puts "running a thread"
        after 1000 loop
    }
    loop
}

while 1 {
    puts "loop"
    after 500
}
person slebetman    schedule 19.11.2010
comment
Спасибо, примеры из вики Tcl, похоже, упускают из виду такую ​​ситуацию. - person elmt; 19.11.2010

Ответ, конечно же, тот, который дал Слебетман. Тем не менее, один из способов отладки такого рода вещей (особенно в более сложных случаях) состоит в том, чтобы ставить перед сообщениями, печатаемыми каждым потоком, результат thread::id и убедиться, что вы печатаете сообщение в начале каждого цикла. Например:

package require Thread

set ::a_thread [thread::create {thread::wait}]

proc start_a {} {
  puts "[thread::id]: Dispatch to $::a_thread"
  thread::send $::a_thread {
    puts "[thread::id]: Running a thread"
  }
  after 1000 a_start
}

proc infinite_loop {} {
  while {1} {
    puts "[thread::id]: Loop"
    after 500
  }
}

start_a
infinite_loop
puts "[thread::id]: Start main event loop"
vwait forever

Это сообщило бы вам, что отправка происходит один раз, что выполнение в другом потоке происходит синхронно (thread::send по умолчанию ожидает завершения выполнения скрипта) и что бесконечный цикл предотвращает запуск основного цикла событий ( и, следовательно, изменение графика отправки). Поскольку вы не знали, кто что делает, конечно, возникла путаница!

person Donal Fellows    schedule 19.11.2010
comment
Очень полезный совет. Это мой первый опыт работы с потоками tcl, так что это поможет в моих будущих начинаниях. - person elmt; 19.11.2010