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。
傳回值
非同步計算 (Async 物件), scanner 建置讀取訊息。
備註
如果超過逾時期間, None 傳回。 這個方法要在代理程式的主體中使用。 針對每個代理程式,最多可以有一個現用並行閱讀器,所以 Receive, TryReceive, Scan 或 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,可攜式執行檔 (PE)。