MailboxProcessor.Scan<'Msg,'T> メソッド (F#)
指定された関数が 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オプションのタイムアウト (ミリ秒単位)。 既定値は Infinite に対応する -1 です。
例外
例外 |
状態 |
---|---|
タイムアウト値を超えたときにスローされます。 |
戻り値
既読メッセージ以外から scanner が構築した非同期計算 (Async オブジェクト)。
解説
このメソッドは、エージェントの本体の内部で使用されます。 同時にアクティブにできるリーダーはエージェントごとに最大 1 つであるため、Receive、TryReceive、Scan、または TryScan の呼び出しは一度に 1 つしかアクティブにできません。 scanner 関数の本体は実行中にロックされますが、ロックは非同期ワークフローの実行前に解放されます。
使用例
Scan メソッドを使用する方法の例を次に示します。 このコードでは、メールボックス プロセッサ エージェントが、実行して結果を計算する一連のシミュレートされたジョブを管理しています。
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 and a computation that produces a single result.
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.Scan(fun (jobId, result, source) ->
let action =
async {
printfn "Canceling job #%d" cancelId
source.Cancel()
}
// Return Some(async) if the job ID matches.
if (jobId = cancelId) then
Some(action)
else
None))
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
cancelJob(!a)
else
printfn "Terminating."
finished <- true
以下にサンプル セッションを示します。
プラットフォーム
Windows 8、Windows 7、Windows Server 2012、Windows Server 2008 R2
バージョン情報
F# コア ライブラリのバージョン
2.0、4.0、Portable でサポート