Async.FromContinuations<'T> 메서드(F#)
현재 성공, 예외 및 취소 연속을 캡처하는 비동기 계산을 만듭니다. 콜백은 최종적으로 지정된 연속 중 하나를 정확히 호출해야 합니다.
네임스페이스/모듈 경로: Microsoft.FSharp.Control
어셈블리: FSharp.Core(FSharp.Core.dll)
// Signature:
static member FromContinuations : (('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
// Usage:
Async.FromContinuations (callback)
매개 변수
callback
형식: ('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit현재 성공, 예외 및 취소 연속을 허용하는 함수입니다.
반환 값
현재 연속에 대해 콜백을 제공하는 비동기 계산입니다.
설명
이 메서드에 대 한 인수 라고 일반적으로 세 가지 연속 함수를 사용 하는 람다 식입니다 cont (성공 연속) ccont (취소 연속) 및 econt (오류 연속)로 다음 코드를 보여 줍니다.:
Async.FromContinuations (fun (cont, ccont, econt) -> ...)
경고
이 메서드를 사용 하는 경우 사용 해야 연속 함수 중 정확히 하나를 호출 하거나 경우 F# 호출에서 예외를 throw econt 예외를 대신 사용 합니다.두 개 이상의 연속 호출 한 번 이상 또는 호출을 연속 된 연속 호출 예외를 throw 하는 경우 모든 후속 비동기 결과 개체가 사용 않은 동작 될 수 있습니다.
예제
다음 예제에서는 Async.FromContinuations를 사용하여 이벤트 기반 비동기 계산을 F# 비동기로 래핑하는 방법을 보여줍니다.
open System
open System.ComponentModel
open System.Windows.Forms
type BackgroundWorker with
member this.AsyncRunWorker (computation, argument : 'T, progressChangedHandler) : Async<'U> =
let workerAsync =
Async.FromContinuations (fun (cont, econt, ccont) ->
let handler = new RunWorkerCompletedEventHandler (fun sender args ->
if args.Cancelled then
ccont (new OperationCanceledException())
elif args.Error <> null then
econt args.Error
else
cont (args.Result :?> 'U))
this.WorkerSupportsCancellation <- true;
this.WorkerReportsProgress <- true
this.DoWork.AddHandler(new DoWorkEventHandler(fun sender args ->
args.Result <- computation(argument, this, args)))
this.ProgressChanged.AddHandler(progressChangedHandler)
this.RunWorkerCompleted.AddHandler(handler)
this.RunWorkerAsync(argument)
)
async {
use! holder = Async.OnCancel(fun _ -> this.CancelAsync())
return! workerAsync
}
let factorial number =
let rec fact number =
match number with
| value when value < 0I ->
raise (InvalidOperationException(sprintf "Cannot compute the factorial of a negative number: %s." (value.ToString())))
| value when value > 2000I ->
raise (InvalidOperationException(sprintf "Input too large: %s" (value.ToString())))
| value when value = 0I -> 1I
| value when value = 1I -> 1I
| number -> number * fact (number - 1I)
fact number
// Recursive isprime function.
let isprime number =
let rec check count =
count > number/2 || (number % count <> 0 && check (count + 1))
check 2
let isprimeBigInt number =
let rec check count =
count > number/2I || (number % count <> 0I && check (count + 1I))
check 2I
let computeNthPrime (number, worker: BackgroundWorker, eventArgs: DoWorkEventArgs) =
if (number < 1) then
invalidOp <| sprintf "Invalid input for nth prime: %s." (number.ToString())
let mutable count = 0
let mutable num = 1I
let isDone = false
while (count < number && not eventArgs.Cancel ) do
if (worker.CancellationPending) then
eventArgs.Cancel <- true
else
let percentComplete = int ((float count) / (float number) * 100.0)
worker.ReportProgress(percentComplete, num.ToString())
num <- num + 1I
if (num < bigint System.Int32.MaxValue) then
while (not (isprime (int num))) do
num <- num + 1I
else
while (not (isprimeBigInt num)) do
num <- num + 1I
count <- count + 1
num
let async1 (progressBar:ProgressBar) (label:Label) value =
let worker = new BackgroundWorker()
label.Text <- "Computing..."
let computation value = worker.AsyncRunWorker(computeNthPrime, value,
(fun sender eventArgs ->
label.Text <- "Scanning ... " + eventArgs.UserState.ToString()
progressBar.Value <- eventArgs.ProgressPercentage ))
Async.StartWithContinuations(
computation value,
(fun result -> label.Text <- sprintf "Result: %s" (result.ToString())),
(fun exn -> label.Text <- "Operation failed with error:" + exn.Message),
(fun _ -> label.Text <- "Operation canceled."))
let form = new Form(Text = "Test Form", Width = 400, Height = 400)
let panel1 = new Panel(Dock = DockStyle.Fill)
panel1.DockPadding.All <- 10
let spacing = 5
let button1 = new Button(Text = "Start")
let button2 = new Button(Text = "Start Invalid", Top = button1.Height + spacing)
let button3 = new Button(Text = "Cancel", Top = 2 * (button1.Height + spacing))
let updown1 = new System.Windows.Forms.NumericUpDown(Top = 3 * (button1.Height + spacing),
Value = 20m,
Minimum = 0m,
Maximum = 1000000m)
let label1 = new Label (Text = "", Top = 4 * (button1.Height + spacing),
Width = 300, Height = 2 * button1.Height)
let progressBar = new ProgressBar(Top = 6 * (button1.Height + spacing),
Width = 300)
panel1.Controls.AddRange [| button1; button2; button3; updown1; label1; progressBar; |]
form.Controls.Add(panel1)
button1.Click.Add(fun args -> async1 progressBar label1 (int updown1.Value))
button2.Click.Add(fun args -> async1 progressBar label1 (int (-updown1.Value)))
button3.Click.Add(fun args -> Async.CancelDefaultToken())
Application.Run(form)
플랫폼
Windows Windows 서버 2012, Windows Server 2008 R2, Windows 7, 8
버전 정보
F# 코어 라이브러리 버전
지원: 2.0, 4.0, 노트북