progresschanged progressbar net ejemplos ejemplo dowork f# windows-services backgroundworker

f# - progressbar - Escribir un servicio de sondeo de Windows



backgroundworker wpf (1)

Podría sentir la tentación de escribir un bucle simple en un flujo de trabajo asincrónico. Puedes usar do! Async.Sleep interval do! Async.Sleep interval para dormir entre las encuestas - esto tiene dos ventajas: no estás atando un hilo solo para que permanezca inactivo con Thread.Sleep , y the do! verifica automáticamente la cancelación si pasa un CancellationToken en Async.Start .

Además, si su operación de sondeo implica comunicación de red, ya está en un flujo de trabajo asíncrono, por lo que es trivial realizar llamadas de red asincrónicas.

Normalmente escribo servicios de Windows en C #, pero le doy una oportunidad en F #. Para un servicio de votación, como este, normalmente utilizo una clase que he escrito, que es similar a BackgroundWorker . Genera un hilo de fondo y dispara un método OnWork a intervalos regulares. (El código completo está aquí [github] ).

¿Hay alguna otra manera, quizás mejor o más idiomática, de hacer esto en F #? Podría ser una forma mejor de escribir la clase de trabajador de fondo de sondeo o las alternativas incorporadas a ella.

EDITAR

Esto es lo que surgió, basado en la sugerencia de Joel.

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()

El servicio que usa 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)

Ojalá hubiera una forma de evitar el CancellationTokenSource mutable, pero por desgracia.