Asynchronous 如何通过超时停止等待TaskCompletionSource周围的异步包装?

Asynchronous 如何通过超时停止等待TaskCompletionSource周围的异步包装?,asynchronous,f#,task-parallel-library,Asynchronous,F#,Task Parallel Library,假设我有一些无法更改的系统“黑盒”,我想尝试用它做一些工作2秒钟,如果它不能完成-停止并继续其他应用程序: let log msg= 让timestamp=(System.DateTime.UtcNow.ToString(“o”)) printfn“%s:%s”时间戳消息 类型BlackBox()= 让tcs=new System.Threading.Tasks.TaskCompletionSource() 让工作()=异步{ 记录“工作已开始” 让!result=tcs.Task |>Asyn

假设我有一些无法更改的系统“黑盒”,我想尝试用它做一些工作2秒钟,如果它不能完成-停止并继续其他应用程序:

let log msg=
让timestamp=(System.DateTime.UtcNow.ToString(“o”))
printfn“%s:%s”时间戳消息
类型BlackBox()=
让tcs=new System.Threading.Tasks.TaskCompletionSource()
让工作()=异步{
记录“工作已开始”
让!result=tcs.Task |>Async.Task
记录“工作完成”
返回结果}
成员x.DoWork()=工作()
成员x.SetResult()=tcs.TrySetResult(true)
让tryDoWork(box:BlackBox)=异步{
尝试
日志“以2秒超时开始的操作”
Async.RunSynchronously(box.DoWork(),timeout=2000)|>忽略
日志“操作成功”
具有
|ex->log“operation timedout”}
设sut=BlackBox()
tryDoWork sut |>Async.Start
记录“设置任务结果前等待5秒”
Async.Sleep 5000 |>Async.RunSynchronously
记录“设置任务结果”
sut.SetResult()|>忽略
​
​
//输出为:
// ------------------------------------
//2016-02-24T16:45:11.0302884Z:设置任务结果前等待5秒
//2016-02-24T16:45:11.0302884Z:从2秒超时开始的操作
//2016-02-24T16:45:11.0351932Z:工作已开始
//2016-02-24T16:45:16.0322394Z:设置任务结果
//2016-02-24T16:45:16.0351731Z:工作完成
//2016-02-24T16:45:16.0361528Z:运行时间
Async.RunSyncronously with timeout在2秒后抛出TimeoutException,但在这种情况下不会,因为BlackBox内部正在等待任务完成。

TCS(来自@Carsten的评论)这对我来说很有用,因为我无法访问BlackBox内部,如果不更改应用程序的整个设计,我无法更改它,并且需要添加超时的机制,因此不需要取消更长时间的任务

其他建议事项包括:

@凯文:

Async.awaiiasyncresult

正如@kevin所注意到的,我的例子并没有像预期的那样起作用的原因是

带超时的同步运行依赖于给定的异步是可取消的


我还发现了一件事

使用TCS(例如使用
'a选项
)然后使用另一个定时的
async
task
设置
Some
结果,从黑色结果和
None
中选择结果,最后等待等待等待处理注意:这当然不会取消/中止较长的任务-如果需要,请先尝试取消令牌(如果您有)-如果没有,则必须执行(不推荐)
任务。中止
路线