Share via


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 가 반환 됩니다. 이 메서드는 에이전트 본문 내에서 사용됩니다. 각 에이전트에 대해 최대 하나의 동시 판독기만 활성화될 수 있으므로 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# Core 라이브러리 버전

2.0, 4.0, 노트북 지원

참고 항목

참조

Control.MailboxProcessor<'Msg> 클래스(F#)

Microsoft.FSharp.Control 네임스페이스(F#)