MailboxProcessor.TryScan<'Msg,'T> 方法 (F#)

通过按到达顺序浏览消息来扫描消息,直至提供的函数返回 Some 值为止。 其他消息保留在队列中。

命名空间/模块路径: Microsoft.FSharp.Control

程序集:FSharp.Core(在 FSharp.Core.dll 中)

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

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

参数

  • scanner
    类型:'Msg -> Async<'T> option

    用于在跳过消息时返回 None 、 在处理消息并将其从队列中移除时返回 Some 的函数。

  • timeout
    类型:int

    可选超时(以毫秒为单位)。 默认值为 -1,它对应于 Infinite

返回值

scanner 脱离读取消息生成的异步计算(Async 对象)。

备注

如果超时时间已过,None 返回。 此方法可在代理的主体内使用。 对于每个代理至多只有一个并发读取器可处于活动状态,因此 ReceiveTryReceiveScan 或者 TryScan 中至多只有一个处于活动状态。 scanner 函数的正文在其执行期间被锁定,但会在执行异步工作流之前解锁。

示例

下面的代码示例演示如何使用 TryScan 方法。 此示例是作业提交代理。 有三个代理:启动每个工作的一个调用 runAgent,另一个名为的 inprogressAgent表示所有正在运行的工作,并且,completeAgent表示一个调用工作完成的通知。 如果没有匹配的工作,TryScan 用于 cancelJob 功能找到工作将会移除,或将失败。

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

下面是为示例部分。

                

平台

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

版本信息

F# 核心库版本

支持:2.0,4.0,可移植

请参见

参考

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

Microsoft.FSharp.Control 命名空间 (F#)