Timeout on Stream Reads

H

Helge Jensen

I am implementing a protocol which transmits messages. The messages are
most naturally transferred using the a Stream so the protocol can
communicate over serial-ports, network links, ....

If the other party never answers I must timeout -- not block, and this
gives me a problem, since the Stream concept in .NET does not reflect
timeouts. If a timeout occurs I will still need to use the same Stream
for more messages, for example re-sends.

For implementing timeouts i have explored some solutions:

- Using async IO: this allows me to use WaitHandle.WaitOne with a
timeout. But when A timeout occurs cancelling the pending async-io
operations (and the reulting synchronization) is a problem.

- Using Socket.Select/Socket.Poll: Far from all Streams are based on
Socket, and I can't retrieve the Socket anyway since it's a protected
property in NetworkStream.

I've been googling a bit on stuff like .NET, C#, timeout, stream, read,
but it doesn't turn up much usefull info.

What could I do here? Basically i just wish to have an option to
wait-with-timeout ("select" or "poll" in unix/sockets terminology) for a
guarantee that Read will not block indefinatly if invoked.
 
J

Jon Skeet [C# MVP]

Helge Jensen said:
I am implementing a protocol which transmits messages. The messages are
most naturally transferred using the a Stream so the protocol can
communicate over serial-ports, network links, ....

If the other party never answers I must timeout -- not block, and this
gives me a problem, since the Stream concept in .NET does not reflect
timeouts. If a timeout occurs I will still need to use the same Stream
for more messages, for example re-sends.

For implementing timeouts i have explored some solutions:

- Using async IO: this allows me to use WaitHandle.WaitOne with a
timeout. But when A timeout occurs cancelling the pending async-io
operations (and the reulting synchronization) is a problem.

- Using Socket.Select/Socket.Poll: Far from all Streams are based on
Socket, and I can't retrieve the Socket anyway since it's a protected
property in NetworkStream.

I've been googling a bit on stuff like .NET, C#, timeout, stream, read,
but it doesn't turn up much usefull info.

What could I do here? Basically i just wish to have an option to
wait-with-timeout ("select" or "poll" in unix/sockets terminology) for a
guarantee that Read will not block indefinatly if invoked.

Have you tried setting a timer and closing the stream from another
thread?
 
H

Helge Jensen

Jon said:
Have you tried setting a timer and closing the stream from another
thread?

Thanks for your suggestion, that thought also crossed my mind as a way
to interrupt the async IO. Unfortunatly, closing the stream is not an
option. Usually I will have to retry by retransmitting the same message
down the same stream once more a few times.

Specifically, the stream does not guarantee transmission integrity to
the endpoint. Often it is a reliable network-connection, or a direct
serial connection, to a radio-network bridge which provides rather
unreliable transmission of data to the end destination. Closing the
connection to the bridge is not a good way to retry communication in the
radio network.
 
H

Helge Jensen

Helge said:
For implementing timeouts i have explored some solutions:

- Using async IO: this allows me to use WaitHandle.WaitOne with a
timeout. But when A timeout occurs cancelling the pending async-io
operations (and the reulting synchronization) is a problem.

I have implemented a solution based on this approach. it uses buffering
to avoid cancelling the pending async-io operation. It's not altogether
too pretty and only works on Streams that implement BeginRead
asynchoneously, but it seems to be my only option.

The code (including a test) is available from SVN at
http://slog.dk/svn/home/jensen/source/timeoutstream/trunk/ if anybody
feels like taking it to the cleaners :)

On unix system, pretty much every IO-thingy have a "file-descriptor"
which is accessible by some kind of means and passable to select/poll. I
was hoping that the corresponding Socket abstraction in .NET was exposed
in Stream, or that Stream would expose a publicly available WaitHandle
that i could Wait-All/Any on. I guess I'll have to live without any of
that proven functionality ;)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top