更新:2011 年 1 月
通过按到达顺序浏览消息来扫描消息,直至提供的函数返回 Some 值为止。 其他消息保留在队列中。
命名空间/模块路径: Microsoft.FSharp.Control
程序集:FSharp.Core(在 FSharp.Core.dll 中)
// Signature:
member this.Scan : ('Msg -> Async<'T> option) * ?int -> Async<'T>
// Usage:
mailboxProcessor.Scan (scanner)
mailboxProcessor.Scan (scanner, timeout = timeout)
参数
scanner
类型:'Msg -> Async<'T> option用于在跳过消息时返回 None 、 在处理消息并将其从队列中移除时返回 Some 的函数。
timeout
类型:int可选超时(以毫秒为单位)。 默认值为 -1,它对应于 Infinite()。
异常
异常 |
Condition |
---|---|
在超过超时的情况下引发。 |
返回值
scanner 脱离读取消息生成的异步计算(Async 对象)。
备注
此方法可在代理的主体内使用。 对于每个代理,至多只有一个并发读线程可处于活动状态,因此不能有多个对 Receive, TryReceive, Scan 或 TryScan 的并发调用处于活动状态。 scanner 函数的正文在其执行期间被锁定,但会在执行异步工作流之前解锁。
示例
下面的示例演示如何使用 Scan 方法。 在此代码中,邮箱处理器代理管理一系列运行和计算结果的模拟作业。
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
示例会话如下。
平台
Windows 7、Windows Vista SP2、Windows XP SP3、Windows XP x64 SP2、Windows Server 2008 R2、Windows Server 2008 SP2、Windows Server 2003 SP2
版本信息
F# 运行时
受以下版本支持:2.0、4.0
Silverlight
受以下版本支持:3
请参见
参考
Control.MailboxProcessor<'Msg> 类 (F#)
Microsoft.FSharp.Control 命名空间 (F#)
修订记录
Date |
修订记录 |
原因 |
---|---|---|
2011 年 1 月 |
添加了代码示例。 |
信息补充。 |
2011 年 4 月 |
更正了有关超时行为的信息。 |
内容 Bug 修复 |