F#hot to stop Async.Start

Sep 04 2020

こんにちは私は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*)}

そして、更新された接続プールでこのタスクを再開できますが、それができるかどうかわかりません。私の質問は、そのようなタスクを停止することは可能ですか、そうでない場合はそれを行うためのより良い方法がありますか?

回答

4 TomasPetricek Sep 04 2020 at 20:56

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から戻ることもできます。StartObservable

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ます。