Обычно я пишу службы Windows на C #, но я пробуюсь на F #. Для такой службы опроса, как эта, я обычно использую написанный мной класс, похожий на BackgroundWorker
. Он порождает фоновый поток и через регулярные промежутки времени запускает метод OnWork . (Полный код здесь [github] .)
Есть ли другой, возможно, лучший или более идиоматический способ сделать это в F #? Это может быть лучший способ написать рабочий класс фонового опроса или встроенные альтернативы ему.
Вот что я придумал, основываясь на предложении Джоэла.
module Async =
open System.Diagnostics
let poll interval work =
let sw = Stopwatch()
let rec loop() =
async {
sw.Restart()
work()
sw.Stop()
let elapsed = int sw.ElapsedMilliseconds
if elapsed < interval then
do! Async.Sleep(interval - elapsed)
return! loop()
}
loop()
//Example
open System.Threading
let cts = new CancellationTokenSource()
Async.Start(Async.poll 2000 (fun () -> printfn "%A" DateTime.Now), cts.Token)
Thread.Sleep(TimeSpan.FromSeconds(10.0))
cts.Cancel()
Служба, использующая опрос
:
type MyService() =
inherit System.ServiceProcess.ServiceBase()
let mutable cts = new CancellationTokenSource()
let interval = 2000
override __.OnStart(_) =
let polling = Async.poll interval (fun () ->
//do work
)
Async.Start(polling, cts.Token)
override __.OnStop() =
cts.Cancel()
cts.Dispose()
cts <- new CancellationTokenSource()
override __.Dispose(disposing) =
if disposing then cts.Dispose()
base.Dispose(true)
Хотелось бы найти способ избежать изменяемого CancellationTokenSource
, но, увы.