英文:
How to do a read with timeout on IO
问题
以下是您要翻译的代码部分:
function read_with_timeout(io::IO, timeout::Int)
read(io, UInt16)
end
function read_with_timeout(io::IO, type::Type, timeout::Int)
sleepTime = 0.01
totalTime = 0
value = nothing
@async value = read(io, type)
while value === nothing
if totalTime >= timeout
throw(TimeoutException())
end
sleep(sleepTime)
totalTime += sleepTime
end
value
end
英文:
How do I add a timeout for reading from an IO in julia?
function read_with_timeout(io::IO, timeout::Int)
read(io, UInt16)
end
Is this a good impl?
function read_with_timeout(io::IO, type::Type, timeout::Int)
sleepTime = 0.01
totalTime = 0
value = nothing
@async value = read(io, type)
while value === nothing
if totalTime >= timeout
throw(TimeoutException())
end
sleep(sleepTime)
totalTime += sleepTime
end
value
end
答案1
得分: 2
这种轮询任务的一般思路绝对是有效的解决方案。如果你测量实际触发超时所需的时间,你会发现它比请求的超时时间长。它总是会稍微长一些,但通过测量已经过去的时间而不是假设sleepTime
已经过去,我们可以更准确。
你的函数与Base.timedwait非常相似,它在测量方面更加谨慎。以下是带有timedwait
的函数版本:
function read_with_timeout(io, type, timeout)
task = @async read(io, type)
status = timedwait(timeout) do
istaskdone(task)
end
if status == :ok
fetch(task)
else
throw(TimeoutException())
end
end
这个函数在这个实现和你的实现中都存在一个更严重的问题。已启动的任务仍然在等待数据,并且会默默地消耗任何可用的数据。
一个更好的解决方案可能可以通过使用更低级别的读取函数找到,但我们也可以中断任务(要注意竞争条件):
function read_with_timeout(io, type, timeout)
task = @async read(io, type)
status = timedwait(timeout) do
istaskdone(task)
end
if status == :ok
fetch(task)
else
@async Base.throwto(task, TimeoutException())
fetch(task)
end
end
英文:
The general idea of polling the task this way is definitely a valid solution. If you measure the actual time it takes for the timeout to trigger in your implementation you'll see that it takes longer thsn the requested timeout. It will always be slightly longer but we can be more accurrate by measuring the time that has passed instead of assuming that sleepTime
had passed.
Your function is very similar to Base.timedwait which does the measuring a bit more carefully. Here is a version of the function with timedwait
:
function read_with_timeout(io, type, timeout)
task = @async read(io, type)
status = timedwait(timeout) do
istaskdone(task)
end
if status == :ok
fetch(task)
else
throw(TimeoutException())
end
end
There is a more serious issue with this function in both this implementation and your implementation. The started task is still around waiting for data and will silently consume any available data.
A nicer solution could probably be found by reaching for lower level reading functions but we can also interrupt the task (be mindful of race conditions):
function read_with_timeout(io, type, timeout)
task = @async read(io, type)
status = timedwait(timeout) do
istaskdone(task)
end
if status == :ok
fetch(task)
else
@async Base.throwto(task, TimeoutException())
fetch(task)
end
end
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论