GetRequestAsync究竟是如何工作的?

时间:2015-09-08 15:54:26

标签: c# rest asynchronous httpwebrequest

我想在上传大文件时,我遗漏了HttpWebRequest如何通过流媒体工作。 基本上,我发现在向服务器发送大文件时会收到超时异常,因此建议通过异步执行此操作并自行处理超时。

问题是,在调试之后,我发现了“GetRequestStreamAsync”方法,并且写入它在服务器端什么都不做,只在执行GetResponseAsync时调用服务器

所以我的问题是:

- 标记为// 1的代码 - 它将文件写入请求流,但我没有看到内存正在增加,或者服务器甚至没有得到任何请求 - 流式传输到哪里?

这基本上就是我的代码:

            HttpWebRequest request = RESTUtils.InitializeRequest(...);

            request.AllowWriteStreamBuffering = false;
            request.ContentLength = i_InputStream.Length;
            request.Timeout = 5000;  

            using (Stream requestStream = request.GetRequestStreamWithTimeout())
            {
               if (requestStream != null) //1
               {
                  // We will write the stream to the request
                  byte[] buffer = new byte[UPLOAD_FILE_BUFFER_SIZE];
                  int read = i_InputStream.Read(buffer, 0, buffer.Length);

                  while (read > 0)
                  {
                     requestStream.Write(buffer, 0, read);                         
                     read = i_InputStream.Read(buffer, 0, buffer.Length);
                  }
               }
            }

            using (var response = request.GetResponseWithTimeout(-1))
            {
               using (var responseStream = response.GetResponseStream())
               {

               }
            }

public static class WebRequestExtensions
   {
      public static Stream GetRequestStreamWithTimeout(
          this WebRequest request,
          int? millisecondsTimeout = null)
      {
         return AsyncToSyncWithTimeout(
             request.BeginGetRequestStream,
             request.EndGetRequestStream,
             millisecondsTimeout ?? request.Timeout);
      }

      public static WebResponse GetResponseWithTimeout(
          this HttpWebRequest request,
          int? millisecondsTimeout = null)
      {
         return AsyncToSyncWithTimeout(
             request.BeginGetResponse,
             request.EndGetResponse,
             millisecondsTimeout ?? request.Timeout);
      }

      private static T AsyncToSyncWithTimeout<T>(
          Func<AsyncCallback, object, IAsyncResult> begin,
          Func<IAsyncResult, T> end,
          int millisecondsTimeout)
      {
         var iar = begin(null, null);
         if (!iar.AsyncWaitHandle.WaitOne(millisecondsTimeout))
         {
            var ex = new TimeoutException();
            throw new WebException(ex.Message, ex, WebExceptionStatus.Timeout, null);
         }
         return end(iar);
      }
   }

谢谢!

==编辑9/9/15 ==

甚至更奇怪的事情发生了,我在GetResponseAsync之后立即附加断点,然后我看到服务器接收到呼叫。 之后,我正在关闭客户端的流程 - &gt;服务器正在成功上传文件。

如果我做“中止”,也会发生这种情况。 有谁知道为什么?

1 个答案:

答案 0 :(得分:0)

不应使用旧式的开始/结束异步模式,而应考虑切换到async/await,这将大大简化您的代码。

然后,您可以根据请求将Timeout属性设置为较大的值以适应您的等待时间;然后你可以这样做,而不是使用基于回调的异步代码:

var request = SomeMethodToCreateRequest();
request.Timeout = int.MaxValue; // (don't do this)
var response = await request.GetResponse();

应该在内部遵守超时,您可以简化代码。