Metodo MailboxProcessor.Scan<'Msg,'T> (F#)
Cerca un messaggio analizzando i messaggi in ordine di arrivo finché una funzione fornita non restituisce un valore Some. Gli altri messaggi rimangono nella coda.
Percorso di spazio dei nomi/modulo: Microsoft.FSharp.Control
Assembly: FSharp.Core (in FSharp.Core.dll)
// Signature:
member this.Scan : ('Msg -> Async<'T> option) * ?int -> Async<'T>
// Usage:
mailboxProcessor.Scan (scanner)
mailboxProcessor.Scan (scanner, timeout = timeout)
Parametri
scanner
Tipo: 'Msg -> Async<'T> optionFunzione che restituisce None se il messaggio deve essere ignorato oppure Some se il messaggio deve essere elaborato e rimosso dalla coda.
timeout
Tipo: intTimeout facoltativo in millisecondi. L'impostazione predefinita è -1, che corrisponde a Infinite().
Eccezioni
Eccezione |
Condizione |
---|---|
Generata se viene superato il timeout. |
Valore restituito
Calcolo asincrono (oggetto asincrono) che scanner compilato al di fuori del messaggio di lettura.
Note
Questo metodo deve essere utilizzato all'interno del corpo dell'agente. Per ogni agente può essere attivo al massimo un lettore simultaneo, pertanto non può essere attiva più di una chiamata simultanea di Receive, TryReceive, Scan o TryScan. Il corpo della funzione scanner viene bloccato durante l'esecuzione, ma il blocco viene rilasciato prima dell'esecuzione del flusso di lavoro asincrono.
Esempio
Nell'esempio seguente viene illustrato come utilizzare il metodo Scan. In questo codice, gli agenti del processore della cassetta postale gestiscono una serie di processi simulati che eseguono e calcolano un risultato.
open System
let numProcs = Environment.ProcessorCount
type Job<'Result> = int * Async<'Result>
// Request to run a job, or
// Completed notification (with proc id and jobId
type RequestMessage<'Result> =
| Request of Job<'Result>
| Completed of int * int
// Contains the id of the proc and the job
type RunMessage<'Result> = int * Job<'Result>
let random = System.Random()
// The program computes the Nth prime numbers for various
// values of N.
// This number determines how large values of N are.
let multiplier = 5000
// Generates mock jobs using Async.Sleep.
let createJob(id:int, computation, input:int) =
let job = async {
let result = computation(input)
return result
}
id, job
let execAgents = Array.zeroCreate<MailboxProcessor<RunMessage<_>>> numProcs
let controllerAgent = new MailboxProcessor<RequestMessage<_>>(fun inbox ->
// First try to identify an idle proc by calling tryFindIndex.
// If there is an idle proc, scan for a request and run it.
// If there is not an idle proc, scan for an idle notification.
// No timeout given, so scan may wait indefinitely either to receive
// a new request, or for a proc to signal that it's idle. Meanwhile,
// messages build up in the queue.
// An array indicating whether each proc is idle.
let idleStatus = Array.create numProcs true
let rec loop (count) =
async {
let idleId = Array.tryFindIndex (fun elem -> elem) idleStatus
match idleId with
| Some id ->
do! inbox.Scan(function | Request((jobId, _) as job) ->
Some(async {
idleStatus.[id] <- false
printfn "Job #%d submitted." jobId
execAgents.[id].Post(id, job) })
| Completed _ -> None)
| None ->
do! inbox.Scan(function | Request _ -> None
| Completed (id, jobId) ->
Some(async { idleStatus.[id] <- true }))
do! loop (count + 1)
}
loop 0)
for procId in 0 .. numProcs - 1 do
execAgents.[procId] <- new MailboxProcessor<RunMessage<_>>(fun inbox ->
let rec loop (count) =
async {
let! procId, (jobId, job) = inbox.Receive()
// Start the job
// Post to the controller inbox when complete.
// The exception and cancellation continuations are not used.
printfn "Job #%d started on procId %d." jobId procId
Async.Start(async {
let! result = job
printfn "Job #%d completed." jobId
printfn "Nth Prime for N = %d is %s." (multiplier*jobId) (result.ToString())
controllerAgent.Post(Completed(procId, jobId))
})
do! loop (count + 1)
}
loop 0)
execAgents.[procId].Start()
controllerAgent.Start()
let numJobs = 10
printfn "Number Of Logical Processors: %d" numProcs
let isprime number = number > 1 && Seq.forall (fun n -> number % n <> 0) { 2 .. number/2 }
let nthPrime n = Seq.initInfinite (fun n -> n)
|> Seq.filter (fun n -> isprime n)
|> Seq.nth (n - 1)
let rec loop (count) =
let jobId = (numJobs - count)
let job = createJob(jobId, (fun n -> nthPrime(n)), multiplier * jobId )
printfn "Requesting job #%d" jobId
controllerAgent.Post(Request(job))
// Delay
System.Threading.Thread.Sleep(1000);
match count with
| 0 -> ()
| _ -> loop (count - 1)
loop (numJobs - 1)
printfn "Done submitting jobs. Press Enter to exit when ready."
Console.ReadLine() |> ignore
Di seguito viene riportata una sessione di esempio.
Piattaforme
Windows 7, Windows Vista SP2, Windows XP SP3, Windows XP x64 SP2, Windows Server 2008 R2, Windows Server 2008 SP2, Windows Server 2003 SP2.
Informazioni sulla versione
F# Runtime
Supportato in: 2.0, 4.0
Silverlight
Supportato in: 3
Vedere anche
Riferimenti
Classe Control.MailboxProcessor<'Msg> (F#)
Spazio dei nomi Microsoft.FSharp.Control (F#)
Cronologia delle modifiche
Data |
Cronologia |
Motivo |
---|---|---|
Gennaio 2011 |
Aggiunto esempio di codice. |
Miglioramento delle informazioni. |
Aprile 2011 |
Sono state corrette le informazioni sul comportamento del timeout. |
Correzione di bug nel contenuto. |