У меня есть потенциально очень долго работающая функция, которая иногда может зависать. Итак, я подумал, что если я включу его в рабочий процесс async
, то я смогу отменить его. Вот пример FSI, который не работает (но то же самое происходит с скомпилированным кодом):
open System.Threading
let mutable counter = 0
/// Emulates an external C# sync function that hung up.
/// Please, don't change it to some F# async stuff because
/// that won't fix that C# method.
let run() =
while true
do
printfn "counter = %A" counter
Thread.Sleep 1000
counter <- counter + 1
let onRunModel() =
let c = new CancellationTokenSource()
let m = async { do run() }
Async.Start (m, c.Token)
c
let tryCancel() =
printfn "Starting..."
let c = onRunModel()
printfn "Waiting..."
Thread.Sleep 5000
printfn "Cancelling..."
c.Cancel()
printfn "Waiting again..."
Thread.Sleep 5000
printfn "Completed."
#time
tryCancel()
#time
Если вы запустите его в FSI, вы увидите нечто подобное:
Starting...
Waiting...
counter = 0
counter = 1
counter = 2
counter = 3
counter = 4
Cancelling...
Waiting again...
counter = 5
counter = 6
counter = 7
counter = 8
counter = 9
Completed.
Real: 00:00:10.004, CPU: 00:00:00.062, GC gen0: 0, gen1: 0, gen2: 0
counter = 10
counter = 11
counter = 12
counter = 13
counter = 14
counter = 15
counter = 16
, что означает, что он вообще не останавливается после вызова c.Cancel()
.
Что я делаю не так и как заставить это работать?
Вот некоторая дополнительная информация :
- Когда код зависает, он делает это в какой-то внешней библиотеке syn c C#, которую я не могу контролировать. Поэтому проверка на токен отмены в коде, который я контролирую, бесполезна. Вот почему функция
run()
выше была смоделирована таким образом. - Мне не нужно сообщение о завершении и / или прогрессе. Это уже сделано через какую-то систему обмена сообщениями, и это выходит за рамки вопроса.
- По сути, мне просто нужно убить фоновую работу, как только я "решу" сделать это.