在F#中运行超时的IO任务



我正在尝试与F#中的云服务进行对话,并在这些操作周围超时。

现在已经进行了多次迭代,但我仍然不知道如何使用Async。

let tokenSource = new CancellationTokenSource()
let task        = Async.StartAsTask(async {return (getS3Meta keyMeta)}, TaskCreationOptions.None, tokenSource.Token)
let metaMaybe   = Async.AwaitTask(task, 700) |> Async.RunSynchronously

为了支持超时,我们引入了:

type Timeout = Timeout
type Microsoft.FSharp.Control.Async with
static member AwaitTask (t : Task<'T>, timeout : int) =
async {
use cts = new CancellationTokenSource()
use timer = Task.Delay (timeout, cts.Token)
let! completed = Async.AwaitTask <| Task.WhenAny(t, timer)
if completed = (t :> Task) then
cts.Cancel ()
let! result = Async.AwaitTask t
return Ok result
else return Error Timeout
}

无论我做什么,任务总是在等待激活。

IO操作超时的推荐方式是什么,它可以阻止主执行,我这里不需要异步代码。如果我必须使用async,那么用于启动有超时的任务的原语是什么?

当前正在工作的代码(尽管我们不了解与不同异步工作流相关的不同权衡,但我们没有遇到此问题(。

let doSomeIoAsync =
async {
return (anotherAsyncWokFlowIoInCsharpLib someParam)
}
let task = Async.StartAsTask doSomeIoAsync
match task.Wait(500) with
| true ->  Success task.Result
| false -> Error Timeout

一些fsi:

> let ioFn () = Thread.Sleep(5000); System.Console.WriteLine 100; 100;;
Real: 00:00:00.000, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val ioFn : unit -> int
> ioFn();;
100
Real: 00:00:05.005, CPU: 00:00:00.001, GC gen0: 0, gen1: 0, gen2: 0
val it : int = 100
> let taskAsync = async { return ioFn() };;
Real: 00:00:00.000, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val taskAsync : Async<int>
> let t = Async.StartAsTask taskAsync ;;
Real: 00:00:00.000, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val t : Tasks.Task<int>
> t.Wait(500) ; t.Status;;
Real: 00:00:00.505, CPU: 00:00:00.001, GC gen0: 0, gen1: 0, gen2: 0
val it : Tasks.TaskStatus = WaitingForActivation
> 100
- t.Wait(500) ; t.Status;;
Real: 00:00:00.000, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val it : Tasks.TaskStatus = RanToCompletion
> t.Result;;
Real: 00:00:00.000, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val it : int = 100

我认为这样使用WaitingForActivation有点误导。也许我误解了这一点,这真的是在等待完成。

就性能而言,前两个请求与其他请求相比非常慢:

Error: WaitingForActivation
Elapsed Time: 296
Error: WaitingForActivation
Elapsed Time: 254
Error: WaitingForActivation
Elapsed Time: 255
Error: WaitingForActivation
Elapsed Time: 254
Error: WaitingForActivation
Elapsed Time: 254
OK: RanToCompletion
Elapsed Time: 249
OK: RanToCompletion
Elapsed Time: 147
OK: RanToCompletion
Elapsed Time: 246
OK: RanToCompletion
Elapsed Time: 146
OK: RanToCompletion
Elapsed Time: 150
OK: RanToCompletion
Elapsed Time: 142
OK: RanToCompletion
Elapsed Time: 143
OK: RanToCompletion
Elapsed Time: 139
OK: RanToCompletion
Elapsed Time: 139
OK: RanToCompletion
Elapsed Time: 141

不知道如何摆脱起步缓慢的局面。

最新更新