Sdílet prostřednictvím


MailboxProcessor.Scan<'Msg,'T> – metoda (F#)

Vyhledá zprávu projitím zpráv v pořadí doručení, dokud zadaná funkce nevrátí hodnotu Some.Ostatní zprávy zůstávají ve frontě.

Obor názvů/cesta modulu: Microsoft.FSharp.Control

Sestavení: FSharp.Core (v FSharp.Core.dll)

// Signature:
member this.Scan : ('Msg -> Async<'T> option) * ?int -> Async<'T>

// Usage:
mailboxProcessor.Scan (scanner)
mailboxProcessor.Scan (scanner, timeout = timeout)

Parametry

  • scanner
    Zadejte: 'Msg -> Async<'T> option

    Funkce, která vrací None, pokud má být zpráva vynechána, nebo Some, pokud má být zpráva zpracována a odebrána z fronty.

  • timeout
    Zadejte: int

    Volitelný časový limit v milisekundách.Výchozí hodnota -1, což odpovídá Infinite.

Výjimky

Výjimka

Podmínka

TimeoutException

Vyvolána, pokud je překročen časový limit.

Vrácená hodnota

Asynchronní výpočet (objekt Async), který scanner vytvořil z přečtené zprávy.

Poznámky

Tato metoda je určena pro použití v těle agenta.Pro každého agenta může být aktivní nejvýše jeden souběžný čtenář, nemůže být tedy aktivních více souběžných volání Receive, TryReceive, Scan nebo TryScan.Tělo funkce scanner je uzamčeno během svého provádění, ale zámek je uvolněn před spuštěním asynchronního pracovního postupu.

Příklad

Následující příklad ukazuje způsob použití metody Scan.V tomto kódu agenti zpracování poštovní schránky spravují řady simulovaných úloh, které spouští a počítají výsledek.

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

Následuje ukázková relace.

     

Platformy

Windows 8, Windows 7, Windows Server 2012, Windows Server 2008 R2

Informace o verzi

Verze základní knihovny F#

Podporováno ve verzích: 2.0, 4.0, Portable

Viz také

Referenční dokumentace

Control.MailboxProcessor<'Msg> – třída (F#)

Microsoft.FSharp.Control – obor názvů (F#)