F#热停止Async.Start

问题描述

嗨,我有一个关于F#中异步的问题。

因此,我有一个简单的过程,该过程在backgrount中运行,并放置在类型的成员中,如下所示:

type Sender () = 
     member this.Start udpConectionPool = 
        async { (* ome operation that continusly send something to throu udP*) } |> Async.Start

因此,它开始并开始通过UDP连续发送帧,而不会阻塞程序的其余部分,但是我有时会想重新启动线程(让我们说我想添加新的端点,它将把它发送到udpConectionPool参数)。

我正在考虑将任务转储给成员,然后:

member this.Stop = async { do! (*stop async start member that contains task*)}

然后,我可以使用更新的连接池重新启动此任务,但是我不知道是否可以这样做。 我的问题是,是否可以停止此类任务,或者如果没有更好的方法呢?

解决方法

取消F#异步工作流的标准方法是使用CancellationToken。致电Async.Start时,您可以提供取消令牌。当令牌被取消后,异步工作流程将停止(在当前阻止工作完成之后):

open System.Threading

let cts = new CancellationTokenSource()
let work = async { (* ... *) }
Async.Start(work,cts.Token)

cts.Cancel() // Sometime later from another thread

要将其与Sender集成,您可以存储当前的CancellationTokenSource并使用Stop方法来取消它(如果您想将其保留在有状态的类中)。或者,您可以通过IDisposable接口的工作方式,从Start方法返回Observable

type Sender () = 
  member this.Start udpConectionPool = 
    let cts = new CancellationTokenSource()
    let work = async { (* ... *) }
    Async.Start(work,cts.Token)
    { new System.IDisposable with
      member x.Dispose() = cts.Cancel() }

通过这种方式,Start的调用方负责存储返回的IDisposable,并在再次调用Start之前将其处置。