REBOL: Как выполнить другую задачу, ожидая срабатывания будильника? - PullRequest
1 голос
/ 25 апреля 2010

Итак, я создал функцию будильника:

alarm: func[seconds message [string! unset!]][
     wav: load %attention.wav
     sound-port: open sound://
     wait seconds do [
     insert sound-port wav
     wait sound-port
     close sound-port
     if (value? 'message) [
           print message
        ]
   ]
]

, который работает так:

alarm 30 "Will trigger in 30 seconds"

Теперь, как, например, показать таймер, который увеличивается во время ожидания сигнала тревоги, поскольку Rebol не поддерживает поток?

1 Ответ

1 голос
/ 28 апреля 2010

REBOL не имеет традиционной поддержки многозадачности / многопоточности. Тем не менее, вы можете подделать его с помощью графического интерфейса в REBOL / View, который, так как вы используете звук, я предполагаю, что вы используете.

Ключ в том, чтобы установить таймер для одного из объектов интерфейса, который периодически вызывает функцию для проверки состояния объектов, которые вы хотите отслеживать. В этом примере я переписал вашу функцию будильника, чтобы установить переменную данных тревоги, которая будет проверяться периодической функцией, когда она вызывается каждую секунду из объекта монитора в макете (это то, что чувствуют «скорость 1» [задействовать) :: Периодический] "материал делает).

Несмотря на грубость, этот трюк имеет большое значение для компенсации отсутствующих потоков (если вы можете смириться с наличием графического интерфейса). Вы можете проверять / обновлять все виды вещей в периодической функции, даже реализовывать простую многозадачность с помощью конечного автомата. Также обратите внимание, что вы можете настроить данные тревоги в виде списка сигналов тревоги вместо одного, если вам нужно более одного.

Также см. http://www.rebol.com/docs/view-face-events.html для получения дополнительной информации об обработке специальных событий.

REBOL [
    Title: "Alarmer"
    File: %alarm.r
    Author: oofoe
    Date: 2010-04-28
    Purpose: "Demonstrate non-blocking alarm."
]

alarm-data: none

alarm: func [
    "Set alarm for future time."
    seconds "Seconds from now to ring alarm."
    message [string! unset!] "Message to print on alarm."
] [
    alarm-data: reduce [now/time + seconds  message]
]

ring: func [
    "Action for when alarm comes due."
    message [string! unset!]
] [
    set-face monitor either message [message]["RIIIING!"]
    ; Your sound playing can also go here (my computer doesn't have speakers).
]

periodic: func [
    "Called every second, checks alarms."
    fact action event
] [
    if alarm-data [
        ; Update alarm countdown.
        set-face monitor rejoin [
            "Alarm will ring in " 
            to integer! alarm-data/1 - now/time
            " seconds."
        ]

        ; Check alarm.
        if now/time > alarm-data/1 [
            ring alarm-data/2
            alarm-data: none ; Reset once fired.
        ]
    ]
]


view layout [
    monitor: text 256 "Alarm messages will be shown here."  
        rate 1  feel [engage: :periodic]
    button 256 "re/start countdown" [
        alarm 10 "This is the alarm message."
        set-face monitor "Alarm set."
    ]
]
...