Or use BeginXYZ version of the function along with WaitHandle.WaitAny and a
TimeSpan. Then you can pass in other WaitHandle objects at the same time,
like a cancel ManualResetEvent (which could even be set from a different
process). Of course you'll still need to close the socket if the operation
didn't finish in time / user requested cancel.