MailboxProcessor.Scan <'Msg, T' > Método (F#)

Procura uma mensagem, examinando as mensagens na ordem de chegada, até que uma função fornecida retorna um Some valor. Outras mensagens permanecem na fila.

Caminho do namespace/módulo: Microsoft.FSharp.Control

Assembly: FSharp.Core (em 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> opção

    Uma função que retorna None se a mensagem for seja ignorada, ou Some se a mensagem deve ser processado e removido da fila.

  • timeout
    Tipo: int

    Um opcional de tempo limite em milissegundos. Padrão é -1, o que corresponde a Infinite().

Exceções

Exceção

Condição

TimeoutException

Lançada quando o tempo limite for excedido.

Valor de retorno

Uma computação assíncrona (Async objeto) que scanner criado a partir da mensagem de leitura.

Comentários

Retorna None se um tempo limite é dado e o tempo limite for excedido. Este método é para uso dentro do corpo do agente. Para cada agente, no máximo um leitor simultâneo pode estar ativo, portanto, não mais de uma chamada simultânea para receber, TryReceive, Scan ou TryScan pode estar ativo.

Exemplo

The following example shows how to use the Scan method. Nesse código, os agentes do processador de caixa de correio gerenciam uma série de simulado trabalhos executados e calcular um resultado.

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

Segue a uma sessão de amostra.

                                                  

Plataformas

O Windows 7, SP2 do Windows Vista, Windows XP SP3, Windows XP Professional x64 SP2, Windows Server 2008 R2, Windows Server 2008 SP2, Windows Server 2003 SP2

Informações sobre versão

O tempo de execução F#

Compatível com: 2.0, 4.0

Silverlight

Compatível com: 3

Consulte também

Referência

Control.MailboxProcessor <'Msg > Classe (F#)

Microsoft.FSharp.Control Namespace (F#)

Histórico de alterações

Date

History

Motivo

Janeiro de 2011

Exemplo de código adicionado.

Aprimoramento de informações.