Các thử nghiệm sau đây cho thấy rằng Async.Sleep trong F # 2.0 không thể bị hủy bỏ ngay lập tức. Chúng tôi sẽ chỉ nhận được thông báo 'hủy' sau khi thời gian trôi qua.là có bất kỳ lý do tại sao Async.Sleep không thể hủy bỏ ngay lập tức?
module async_sleep_test
open System
open System.Threading
open System.Threading.Tasks
open System.Xml
let cts = new CancellationTokenSource()
Task.Factory.StartNew(fun() ->
try
Async.RunSynchronously(async{
printfn "going to sleep"
do! Async.Sleep(10000)
}, -1(*no timeout*), cts.Token)
printfn "sleep completed"
with
| :? OperationCanceledException ->
printfn "sleep aborted" // we will see it only after 10 sec.
| _ ->
printfn "sleep raised error"
) |> ignore
Thread.Sleep(100) // give time to the task to enter in sleep
cts.Cancel()
Thread.Sleep(100) // give chance to the task to complete before print bye message
printfn "press any key to exit...."
Console.ReadKey(true) |> ignore
Tôi nghĩ rằng đây là hành vi không chính xác. Làm thế nào để bạn nghĩ rằng đây là một lỗi? Sẽ có bất kỳ bất ngờ nếu ví dụ tôi sẽ sử dụng việc thực hiện sau đây:
static member SleepEx(milliseconds:int) = async{
let disp = new SerialDisposable()
use! ch = Async.OnCancel(fun()->disp.Dispose())
do! Async.FromContinuations(fun (success, error, cancel) ->
let timerSubscription = new SerialDisposable()
let CompleteWith =
let completed = ref 0
fun cont ->
if Interlocked.Exchange(completed, 1) = 0 then
timerSubscription.Dispose()
try cont() with _->()
disp.Disposable <- Disposable.Create(fun()->
CompleteWith (fun()-> cancel(new OperationCanceledException()))
)
let tmr = new Timer(
callback = (fun state -> CompleteWith(success)),
state = null, dueTime = milliseconds, period = Timeout.Infinite
)
if tmr = null then
CompleteWith(fun()->error(new Exception("failed to create timer")))
else
timerSubscription.Disposable <- Disposable.Create(fun()->
try tmr.Dispose() with _ ->()
)
)
}