我正在从HttpWebResponse.GetResponseStream()
获取一个我正在读取数据的流。
现在我想实现一个Timeout
属性。最简单的方法是stream.ReadTimeout = timeout
,但这会引发InvalidOperationException -> Timeouts are not supported on this stream
。
鉴于此,我正在尝试自己实现超时属性,但却陷入了处置。这是我到目前为止所得到的:
public class MyStream : Stream {
private readonly Stream _src;
public override int ReadTimeout { get; set; }
public MyStream (Stream src, int timeout) {
ReadTimeout = timeout;
_src = src;
}
public override int Read(byte[] buffer, int offset, int count) {
var timer = new AutoResetEvent(false);
int read = 0;
ThreadPool.QueueUserWorkItem(
_ => {
read = _src.Read(buffer, offset, count);
timer.Set();
});
bool completed = timer.WaitOne(ReadTimeout);
if (completed) {
return read;
}
throw new TimeoutException(string.Format("waited {0} miliseconds", ReadTimeout));
}
此代码的问题是在抛出正在某处正确处理的TimeoutException
之后。它会在_src.Read(buffer, offset, count)
上抛出一个异常,说明_src流被处理掉了。
有没有办法取消ThreadPool方法,还是应该使用更好的方法和哪一种?
由于
修改
正如@JotaBe所问,我是从HttpWebResponse获取流的代码:
_httpRequest = WebRequest.CreateHttp(url);
_httpRequest.AllowReadStreamBuffering = false;
_httpRequest.BeginGetResponse(
result =>
{
try {
_httpResponse = (HttpWebResponse)_httpRequest.EndGetResponse(result);
stream = _httpResponse.GetResponseStream();
}
catch (WebException) {
downloadCompleted.Set();
Abort();
}
finally {
downloadCompleted.Set();
}
},
null);
bool completed = downloadCompleted.WaitOne(15 * 1000);
if (completed) {
return new MyStream(stream, 10000);
}
答案 0 :(得分:2)
如果你没有收到并通过网络服务器回复,你试图超时。你试图在错误的地方做这件事。
要获得回复,您通常会发出请求:
HttpWebResponse response = (HttpWebResponse)request.GetResponse ();
这是可以超时的操作。您必须使用Begin / End异步模式以不同的方式调用它。
有一个完整的例子 MSDN doc for HttpWebRequest.BeginGetResponse Method
此示例使用回调函数。但是,有许多不同的方法可以使用Begin / End。例如,您可以使用IAsyncResult中提供的WaitHandle,如下所示:
IAsyncResult ar = req.BeginGetResponse(yourCallback, null);
bool completed = ar.AsyncWaitHandle.WaitOne(15000 /*your timeout in miliseconds*/);
这将等待15秒。如果响应在此之前到达,则完成将为真。如果没有,完成将是假的。然后,您可以使用HttpWebRequest.Abort()
方法中止请求。
Begin / End模式负责管理必要的线程。
答案 1 :(得分:-1)
我最终使用了Nomad101建议并用try / catch包围了读取。