我在我的tcl代码中使用了一个主脚本,我在其中打开一个udp端口来读取它上面的数据。我使用fileevent使用“vwait”命令进入事件循环。但我不希望由于这个原因阻止主脚本。总之,我希望主流脚本继续流动,等待udp数据事件应该在后台。如何实现这一目标。请帮我。我浪费了很多时间,但一切都在静脉中。任何帮助都会非常明显。
这是我的主要脚本:
#!/usr/bin/env tclsh8.5
proc create_udp_payload { command data } {
set payload ""
append payload $command
append payload [ format %08x [ expr $data ] ]
return $payload
}
proc send_udp_packet { payload } {
puts -nonewline $soc::s [binary format H* $payload]
puts "\nTransmitting the UDP payload $payload"
return 0
}
set DEST_IP_ADDR 10.10.20.241
set DEST_UDP_PORT 5558
set soc::s [udp_open]
puts "Listening on udp port : [fconfigure $soc::s -myport]"
udp_conf $soc::s $DEST_IP_ADDR $DEST_UDP_PORT
fconfigure $soc::s -buffering none -translation binary
fileevent $soc::s readable [list ::udp_listen]
for { set j 0 } { $j < 10 } { incr j} {
puts "Sending read request to read register $j"
set command "00"
append command [format %02x $j]
send_udp_packet [create_udp_payload $command 0x0000]
after 1000
flush $soc::s
}
wait forever #to enter into the event loop
for { set j 2 } { $j < 12 } { incr j} {
puts "Sending write request to write register $j"
set command "80"
append command [format %02x $j]
send_udp_packet [create_udp_payload $command [expr {0x0000 | $j }] ]
after 2000
flush $soc::s
}
实际上我想从硬件中逐个读取10个寄存器,我正在使用for循环,但我没有得到如何进入事件循环。因为它会阻止主脚本。此后,我想逐个编写10个相同硬件的寄存器。任何人都可以修改此代码以便相应地工作。提前感谢........
答案 0 :(得分:0)
我认为使用after idle
“技巧”可以轻松解决您的问题。我们的想法是设置“通道可读”事件处理程序,然后为“事件循环空闲”条件安排执行数据发送代码,然后进入事件循环:
像这样:
# 1. Create and configure the UDP endpoint:
set udp [udp_open ...]
...
# 2. Install "chan readable" callback handlers for that endpoint:
fileevent $udp readable ...
...
# 3. Schedule the one-off callback to send your data:
after idle [list post_data $udp]
# 4. Enter the event loop:
vwait ::done
一旦vwait
被调用,事件循环机器就会看到是否有任何待处理事件(应该没有),并且一旦待处理事件队列耗尽或为空,所有处理程序都安装使用after idle
被调用,您的数据将被发送出去。
请注意,此方法也适用于其他类似情况,例如,没有什么可以阻止您从事件循环调用的其他处理程序安装此类after idle
处理程序。这使您永远不会离开事件循环(如GUI程序和网络服务器通常那样)。