Winforms 如何使用f中的可观测项中断infinte异步循环#

Winforms 如何使用f中的可观测项中断infinte异步循环#,winforms,asynchronous,f#,observable,Winforms,Asynchronous,F#,Observable,我想创建一个异步循环,直到用户按下停止按钮为止。然而,我对f#还是相当陌生,不确定如何做到这一点。Async.AwaitObservable()永远等待用户输入,而Async.Sleep()显然根本不接受任何用户输入 任何帮助都将不胜感激,我当前的代码如下所示: open FSharpx.Control.Observable open System.Windows.Forms module Gui = let form = new Form(Text="I do loops", Top

我想创建一个异步循环,直到用户按下停止按钮为止。然而,我对f#还是相当陌生,不确定如何做到这一点。Async.AwaitObservable()永远等待用户输入,而Async.Sleep()显然根本不接受任何用户输入

任何帮助都将不胜感激,我当前的代码如下所示:

open FSharpx.Control.Observable
open System.Windows.Forms

module Gui =
    let form = new Form(Text="I do loops", TopMost=true,  Width=250,  Height=250)
    let lbl = new Label(Text="loops: 0", Top=10, Left=10)
    let btn1 = new Button(Text="Continue", Top=30, Left=10, Width=60)
    let btn2 = new Button(Text="Stop", Top=60, Left=10, Width=60)
    form.Controls.AddRange [|btn1; btn2; lbl|]

module Main =
    let observables = Observable.merge
                      <| Observable.map (fun _-> 0) Gui.btn1.Click
                      <| Observable.map (fun _-> 1) Gui.btn2.Click

    let rec loop observable n = async{
        Gui.lbl.Text <- (sprintf "loops: %d" n)

        let! somethingObservable = Async.AwaitObservable(observable) 
        match somethingObservable with
            | 0     -> return! loop observable (n+1)
            | 1     -> ()
            | _     -> failwith "Error!"
    }

    Async.StartImmediate(loop observables 0); System.Windows.Forms.Application.Run(Gui.form)
let rec loop n = async {
  Gui.lbl.Text <- (sprintf "loops: %d" n)
  do! Async.Sleep(500)
  return! loop (n+1) }

let cts = new System.Threading.CancellationTokenSource()
Async.StartImmediate(loop 0, cancellationToken = cts.Token)
Gui.btn2.Click |> Observable.add (fun _ -> cts.Cancel())
打开FSharpx.Control.Observable
打开System.Windows.Forms
模块图形用户界面=
让表单=新表单(Text=“I do loops”,最顶端=true,宽度=250,高度=250)
让lbl=新标签(Text=“loops:0”,Top=10,Left=10)
让btn1=新建按钮(Text=“Continue”,顶部=30,左侧=10,宽度=60)
让btn2=新按钮(Text=“Stop”,顶部=60,左侧=10,宽度=60)
form.Controls.AddRange[|btn1;btn2;lbl |]
主模块=
让Observable=Observable.merge
0)Gui.btn1.单击
1) Gui.btn2.Click
让rec循环可观测n=async{
Gui.lbl.Text返回!循环可观察(n+1)
| 1     -> ()
|->failwith“Error!”
}
Async.StartImmediate(循环观测值为0);System.Windows.Forms.Application.Run(Gui.form)
我希望循环的行为也像下面的一样,同时仍然允许用户打破循环。可能吗

    let rec loop observable n = async{
        Gui.lbl.Text <- (sprintf "loops: %d" n)
        do! Async.Sleep(500)
        return! loop observable (n+1)
让rec循环可观察n=async{

Gui.lbl.Text正如傻瓜在评论中提到的,一种方法是使用
CancellationToken
。F#异步工作流具有内置的取消支持,因此,如果在启动工作流时将取消令牌传递给
StartImmediate
,您可以稍后通过触发取消来取消计算代币

在您的情况下,您可以创建一个新的取消令牌,并在单击第二个按钮时取消它。如下所示:

open FSharpx.Control.Observable
open System.Windows.Forms

module Gui =
    let form = new Form(Text="I do loops", TopMost=true,  Width=250,  Height=250)
    let lbl = new Label(Text="loops: 0", Top=10, Left=10)
    let btn1 = new Button(Text="Continue", Top=30, Left=10, Width=60)
    let btn2 = new Button(Text="Stop", Top=60, Left=10, Width=60)
    form.Controls.AddRange [|btn1; btn2; lbl|]

module Main =
    let observables = Observable.merge
                      <| Observable.map (fun _-> 0) Gui.btn1.Click
                      <| Observable.map (fun _-> 1) Gui.btn2.Click

    let rec loop observable n = async{
        Gui.lbl.Text <- (sprintf "loops: %d" n)

        let! somethingObservable = Async.AwaitObservable(observable) 
        match somethingObservable with
            | 0     -> return! loop observable (n+1)
            | 1     -> ()
            | _     -> failwith "Error!"
    }

    Async.StartImmediate(loop observables 0); System.Windows.Forms.Application.Run(Gui.form)
let rec loop n = async {
  Gui.lbl.Text <- (sprintf "loops: %d" n)
  do! Async.Sleep(500)
  return! loop (n+1) }

let cts = new System.Threading.CancellationTokenSource()
Async.StartImmediate(loop 0, cancellationToken = cts.Token)
Gui.btn2.Click |> Observable.add (fun _ -> cts.Cancel())
让rec循环n=async{
Gui.lbl.Text Observable.add(fun->cts.Cancel())

查看取消令牌