Partager via


MailboxProcessor.TryScan<'Msg,'T>, méthode (F#)

Recherche un message en consultant les messages dans l'ordre d'arrivée jusqu'à ce qu'une fonction fournie retourne une valeur Some.Les autres messages demeurent dans la file d'attente.

Espace de noms/Chemin du module : 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)

Paramètres

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

    Fonction qui retourne None si le message doit être ignoré ou Some si le message doit être traité et supprimé de la file d'attente.

  • timeout
    Type : int

    Délai d'attente facultatif en millisecondes.-1 est la valeur par défaut, qui correspond à Infinite.

Valeur de retour

Un calcul asynchrone (objet Async) qui scanner a créé à partir du message lu.

Notes

Si un délai d'attente est dépassé, None est retourné.Cette méthode doit être utilisée dans le corps de l'agent.Pour chaque agent, un lecteur simultané maximum peut être actif, par conséquent un appel simultané au maximum pour Receive, TryReceive, Scan ou TryScan peut être actif.Le corps de la fonction scanner est verrouillé pendant son exécution, mais le verrou est libéré avant l'exécution du flux de travail asynchrone.

Exemple

L'exemple de code suivant montre comment utiliser la méthode TryScan.Cet exemple est un agent de soumission de travaux.Il existe trois agents : il a appelé runAgent qui démarre chaque JOB, un autre inprogressAgent appelé qui représente tous les JOBs en cours de exécution, et il a appelé completeAgent qui représente la notification qu'un travail est terminé.TryScan est utilisé dans la fonction d' cancelJob pour rechercher un travail d'annuler, ou renommé s'il n'existe aucun travail correspondant.

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

Voici un exemple de session.

  
  
  
  
  
  
  
  
  

Plateformes

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

Informations de version

Versions de bibliothèque principale F#

Prise en charge dans : 2,0, 4,0, portables

Voir aussi

Référence

Control.MailboxProcessor<'Msg>, classe (F#)

Microsoft.FSharp.Control, espace de noms (F#)