Ben*_*jol 7 f# asynchronous timeout
我正在尝试下载从我博客的xml备份中引用的3000多张照片.我遇到的问题是,如果其中一张照片不再可用,整个异步会被阻止,因为AsyncGetResponse不会超时.
ildjarn帮助我整理了一个版本的AsyncGetResponse,它在超时时失败了,但是使用它会产生更多的超时 - 就好像刚排队的请求超时一样.似乎所有的WebRequests都是"立即"启动的,唯一让它工作的方法是将超时设置为下载所有这些组合所需的时间:这不是很好,因为这意味着我已经调整了超时,具体取决于图像的数量.
我达到了香草的极限async
吗?我应该考虑反应性扩展吗?
我认为必须有一种更好的方法来发现文件不可用而不是使用超时.我不完全确定,但如果找不到文件,是否有某种方法可以使它抛出异常?然后你可以将async
代码包装在里面try .. with
,你应该避免大多数问题.
无论如何,如果你想编写自己的"并发管理器"并行运行一定数量的请求并将剩余的待处理请求排队,那么F#中最简单的选择就是使用代理(MailboxProcessor
类型).以下对象封装了行为:
type ThrottlingAgentMessage =
| Completed
| Work of Async<unit>
/// Represents an agent that runs operations in concurrently. When the number
/// of concurrent operations exceeds 'limit', they are queued and processed later
type ThrottlingAgent(limit) =
let agent = MailboxProcessor.Start(fun agent ->
/// Represents a state when the agent is blocked
let rec waiting () =
// Use 'Scan' to wait for completion of some work
agent.Scan(function
| Completed -> Some(working (limit - 1))
| _ -> None)
/// Represents a state when the agent is working
and working count = async {
while true do
// Receive any message
let! msg = agent.Receive()
match msg with
| Completed ->
// Decrement the counter of work items
return! working (count - 1)
| Work work ->
// Start the work item & continue in blocked/working state
async { try do! work
finally agent.Post(Completed) }
|> Async.Start
if count < limit then return! working (count + 1)
else return! waiting () }
working 0)
/// Queue the specified asynchronous workflow for processing
member x.DoWork(work) = agent.Post(Work work)
Run Code Online (Sandbox Code Playgroud)
没有比这更容易了.:)
我认为你遇到的问题是问题领域的固有问题(而不仅仅是异步编程模型的问题,尽管它们确实在某种程度上相互作用).
假设您要下载3000张图片.首先,在您的.NET进程中,有一些类似于System.Net.ConnectionLimit或者我忘记名称的东西,例如会限制.NET进程可以同时运行的同时HTTP连接的数量(默认值只是'2 ' 我认为).因此,您可以找到该控件并将其设置为更高的数字,这将有所帮助.
但接下来,您的机器和互联网连接的带宽有限.因此,即使您可以尝试同时启动3000个HTTP连接,每个单独的连接也会因带宽管道限制而变慢.所以这也会与超时相互作用.(这甚至不考虑服务器上有哪种类型的限制/限制.也许如果你发送3000个请求,它会认为你是DoS攻击并将你的IP列入黑名单.)
因此,这是一个真正的问题域,其中良好的解决方案需要一些智能限制和流量控制,以便管理底层系统资源的使用方式.
正如在另一个答案中,F#代理(MailboxProcessors)是一个很好的编程模型,用于创作这样的限制/流控制逻辑.
(即使如此,如果大多数图片文件都像1MB,但是那里混合了1GB文件,那么单个文件可能会超时.)
无论如何,这不是问题的答案,只是指出问题领域本身存在多少内在的复杂性.(也许它也暗示了为什么UI'下载管理器'如此受欢迎.)