F # quente para parar Async.Start
Olá, tenho uma pergunta sobre async em F #.
Portanto, tenho um procedimento simples que é executado em background que é colocado em um membro de um tipo e se parece com:
type Sender () =
member this.Start udpConectionPool =
async { (* ome operation that continusly send something to throu udp*) } |> Async.Start
Então, isso começa e começa a enviar quadros continuamente por UDP sem bloquear o resto do programa, mas de vez em quando eu quero reiniciar o thread (digamos que eu queira adicionar um novo ponto de extremidade que o enviaria para o parâmetro udpConectionPool).
Eu estava pensando em algo como despejar uma tarefa para um membro e então:
member this.Stop = async { do! (*stop async start member that contains task*)}
E então posso reiniciar esta tarefa com o pool de conexão atualizado, mas não sei se posso fazer isso. Minha pergunta é: é possível interromper essa tarefa ou, se não, existe uma maneira melhor de fazê-lo?
Respostas
A maneira padrão de cancelar fluxos de trabalho assíncronos F # é usando a CancellationToken. Ao ligar Async.Start, você pode fornecer um token de cancelamento. Quando o token é cancelado, o fluxo de trabalho assíncrono é interrompido (após o término do trabalho de bloqueio atual):
open System.Threading
let cts = new CancellationTokenSource()
let work = async { (* ... *) }
Async.Start(work, cts.Token)
cts.Cancel() // Sometime later from another thread
Para integrar isso com o Sender, você pode armazenar o atual CancellationTokenSourcee ter um Stopmétodo que o cancela (se quiser mantê-lo dentro de uma classe com estado). Como alternativa, você pode retornar IDisposabledo Startmétodo de maneira semelhante à forma como a Observableinterface funciona:
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() }
Dessa forma, o chamador de Starté responsável por armazenar o que foi devolvido IDisposablee descartá-lo antes de ligar Startnovamente.