编写轮询Windows服务

Dan*_*iel 7 f# windows-services backgroundworker

我通常在C#中编写Windows服务,但我在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()
Run Code Online (Sandbox Code Playgroud)

该服务使用poll:

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)
Run Code Online (Sandbox Code Playgroud)

我希望有办法避免可变CancellationTokenSource,但唉.

Joe*_*ler 5

我可能想在异步工作流中编写一个简单的循环.您可以使用do! Async.Sleep interval轮询之间睡觉-这有两个好处:你不占用一个线程只是把它闲置用Thread.Sleep,和do!如果您将自动注销您检查CancellationTokenAsync.Start.

此外,如果您的轮询操作涉及网络通信,那么您已经处于异步工作流程中,这使得进行异步网络呼叫变得微不足道.