Freigeben über


MailboxProcessor.TryScan<'Msg,'T>-Methode (F#)

Sucht nach einer Meldung, indem die Meldungen in der Reihenfolge ihres Eintreffens geprüft werden, bis eine angegebene Funktion einen Some-Wert zurückgibt. Andere Meldungen verbleiben in der Warteschlange.

Namespace/Modulpfad: Microsoft.FSharp.Control

Assembly: FSharp.Core (in FSharp.Core.dll)

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

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

Parameter

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

    Eine Funktion zur Rückgabe von None, wenn die Meldung übersprungen werden soll, oder Some, wenn die Meldung verarbeitet und aus der Warteschlange entfernt werden soll.

  • timeout
    Typ: int

    Ein optionales Timeout in Millisekunden. Wird standardmäßig auf -1 festgelegt, was Infinite entspricht.

Rückgabewert

Eine asynchrone Berechnung (Async-Objekt), die vom scanner aus der gelesenen Meldung erstellt wurde.

Hinweise

Wenn ein Timeout überschritten wird, wird None zurückgegeben. Diese Methode ist für die Verwendung im Coderumpf des Agents vorgesehen. Für jeden Agent darf maximal ein Reader gleichzeitig aktiv sein. Es darf also nur maximal ein Aufruf von Receive, TryReceive, Scan oder TryScan aktiv sein. Der Text der scanner-Funktion wird während seiner Ausführung gesperrt, die Sperre wird jedoch vor der Ausführung des asynchronen Workflows aufgehoben.

Beispiel

Im folgenden Codebeispiel wird die Verwendung der TryScan-Methode veranschaulicht. Dieses Beispiel ist ein Jobvorlagen-Agent. Es gibt drei Agents: einen runAgent, der jeden Auftrag beginnt, einen inprogressAgent, der alle ausgeführten Aufträge darstellt, und einen completeAgent, der Benachrichtigungen über den Abschluss eines Auftrags anzeigt. TryScan wird in der cancelJob-Funktion verwendet, um nach einem abzubrechenden Auftrag zu suchen, oder andernfalls mit einem Fehler abzubrechen, wenn es keinen entsprechenden Auftrag gibt.

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, a computation that produces a single result, 
// and a cancellation token source object that can be used to cancel the job. 
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.TryScan((fun (jobId, result, source) ->
                let action =
                    async {
                        printfn "Canceling job #%d" cancelId
                        source.Cancel()
                        return cancelId
                    }
                // Return Some(async) if the job ID matches. 
                if (jobId = cancelId) then
                    Some(action)
                else
                    None), 1000))


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 
        match cancelJob(!a) with
        | Some id -> printfn "A job was canceled: job #%d" id
        | None -> printfn "Job not found." 
    else
        printfn "Terminating."
        finished <- true

Im Folgenden wird eine beispielhafte Sitzung dargestellt.

                

Plattformen

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

Versionsinformationen

F#-Kernbibliotheksversionen

Unterstützt in: 2.0, 4.0, Portable

Siehe auch

Referenz

Control.MailboxProcessor<'Msg>-Klasse (F#)

Microsoft.FSharp.Control-Namespace (F#)