您好,我有一个关于 F# 中异步的问题。
因此,我有一个在后台运行的简单过程,该过程放置在类型的成员中,如下所示:
type Sender() =
member this.Start(udpConectionPool) = async {
(* Some operation that continuously sends something over udp*)
} |> Async.Start
Run Code Online (Sandbox Code Playgroud)
因此,这开始并开始通过 UDP 连续发送帧,而不阻塞程序的其余部分,但有时我想重新启动线程(假设我想添加新端点,它将发送到该udpConnectionPool参数)。
我正在考虑将任务转储给成员之类的事情,然后:
member this.Stop() = async {
do! (*stop async start member that contains task*)
}
Run Code Online (Sandbox Code Playgroud)
然后我可以使用更新的连接池重新启动此任务,但我不知道是否可以做到这一点。
我的问题是,是否可以停止这样的任务,或者如果不能,是否有更好的方法来完成?
取消 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
Run Code Online (Sandbox Code Playgroud)
要将其与 集成Sender,您可以存储当前值CancellationTokenSource并有一个Stop取消它的方法(如果您想将其保留在有状态类中)。或者,您可以按照与接口工作方式类似的方式IDisposable从该方法返回:StartObservable
type Sender () =
member this.Start(udpConnectionPool) =
let cts = new CancellationTokenSource()
let work = async { (* ... *) }
Async.Start(work, cts.Token)
{ new System.IDisposable with
member x.Dispose() = cts.Cancel() }
Run Code Online (Sandbox Code Playgroud)
这样, 的调用者Start负责存储返回的结果IDisposable并在再次调用之前将其处理掉Start。