1

tclコードでメインスクリプトを使用しており、udpポートを開いてそこにあるデータを読み取ります。これは、「vwait」コマンドを使用してイベントループに入っているfileeventを使用して作成しました。しかし、これが原因でメインスクリプトがブロックされることは望ましくありません。要するに、メインスクリプトをフローで継続し、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
}

実際、forループを使用しているハードウェアから10個のレジスタを1つずつ読み取りたいのですが、このためにイベントループに入る方法がわかりません。メインスクリプトをブロックするからです。また、その後、同じハードウェアのレジスタを1つずつ書き込みたいと思います。誰かがそれに応じて動作するようにこのコードを変更してください。よろしくお願いします........

4

1 に答える 1

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プログラムやネットワークサーバーが通常行うように)イベントループを離れることはありません。

于 2013-01-28T16:48:19.553 に答える