MailboxProcessor.Scan<'Msg,'T> (Método de F#)
Busca un mensaje desplazándose por los mensajes según el orden de llegada hasta que una función dada devuelve un valor Some. Los demás mensajes permanecen en la cola.
Espacio de nombres/Ruta de acceso del módulo: Microsoft.FSharp.Control
Ensamblado: FSharp.Core (en FSharp.Core.dll)
// Signature:
member this.Scan : ('Msg -> Async<'T> option) * ?int -> Async<'T>
// Usage:
mailboxProcessor.Scan (scanner)
mailboxProcessor.Scan (scanner, timeout = timeout)
Parámetros
scanner
Tipo: 'Msg -> Async<'T> optionFunción que devuelve None si se debe omitir el mensaje o Some si se debe procesar el mensaje y quitarlo de la cola.
timeout
Tipo: intTiempo de espera opcional en milisegundos. Su valor predeterminado es -1, lo que equivale a Infinite.
Excepciones
Excepción |
Condición |
---|---|
Se produce cuando se supera el tiempo de espera. |
Valor devuelto
Cálculo asincrónico (objeto Async) que scanner compiló a partir del mensaje leído.
Comentarios
Este método se usa en el cuerpo del agente. Por cada agente, solo puede haber un lector simultáneo activo como máximo, por lo que no puede haber más de una llamada simultánea activa a Receive, TryReceive, Scan o TryScan. El cuerpo de la función scanner se bloquea durante su ejecución, pero dicho bloqueo se libera antes de la ejecución del flujo de trabajo asincrónico.
Ejemplo
En el siguiente ejemplo, se muestra cómo utilizar el método Scan. En este código, los agentes del procesador del buzón administran una serie de trabajos simulados que ejecutan y calculan un resultado.
open System
open System.Threading
let random = System.Random()
// Generates mock jobs by using Async.Sleep.
let createJob(id:int, source:CancellationTokenSource) =
let job = async {
// Let the time be a random number between 1 and 10000.
// The mock computed result is a floating point value.
let time = random.Next(10000)
let result = random.NextDouble()
let count = ref 1
while (!count <= 100 && not source.IsCancellationRequested) do
do! Async.Sleep(time / 100)
count := !count + 1
return result
}
id, job, source
type Result = double
// A Job consists of a job ID and a computation that produces a single result.
type Job = int * Async<Result> * CancellationTokenSource
type Message = int * Result
let context = System.Threading.SynchronizationContext.Current
// This agent processes when jobs are completed.
let completeAgent = MailboxProcessor<Message>.Start(fun inbox ->
let rec loop n =
async {
let! (id, result) = inbox.Receive()
printfn "The result of job #%d is %f" id result
do! loop (n + 1)
}
loop (0))
// inprogressAgent maintains a queue of in-progress jobs that can be
// scanned to remove canceled jobs. It never runs its processor function,
// so we set it to do nothing.
let inprogressAgent = new MailboxProcessor<Job>(fun _ -> async { () })
// This agent starts each job in the order in which it is received.
let runAgent = MailboxProcessor<Job>.Start(fun inbox ->
let rec loop n =
async {
let! (id, job, source) = inbox.Receive()
printfn "Starting job #%d" id
// Post to the in-progress queue.
inprogressAgent.Post(id, job, source)
// Start the job.
Async.StartWithContinuations(job,
(fun result -> completeAgent.Post(id, result)),
(fun _ -> ()),
(fun cancelException -> printfn "Canceled job #%d" id),
source.Token)
do! loop (n + 1)
}
loop (0))
for id in 1 .. 10 do
let source = new CancellationTokenSource()
runAgent.Post(createJob(id, source))
let cancelJob(cancelId) =
Async.RunSynchronously(
inprogressAgent.Scan(fun (jobId, result, source) ->
let action =
async {
printfn "Canceling job #%d" cancelId
source.Cancel()
}
// Return Some(async) if the job ID matches.
if (jobId = cancelId) then
Some(action)
else
None))
printfn "Specify a job by number to cancel it, then press Enter."
let mutable finished = false
while not finished do
let input = System.Console.ReadLine()
let a = ref 0
if (Int32.TryParse(input, a) = true) then
cancelJob(!a)
else
printfn "Terminating."
finished <- true
A continuación se muestra una sesión de ejemplo.
Plataformas
Windows 8, Windows 7, Windows Server 2012, Windows Server 2008 R2
Información de versiones
Versiones de la biblioteca básica de F#
Se admite en las versiones: 2.0, 4.0, Portable