title: System.Net.HttpClient throws uploading files: The stream does not support concurrent IO read or write operations
body: <p>I'm working on a project that have some runners where each runner could be uploading files simultaneously. Arbitrarily I would get an 'The stream does not support concurrent IO read or write operations' error. </p>
  
  <p>We have seen it happening with small (5Mb~10Mb) and big files too (1Gb~2Gb). We have even tried the exact same files and we are able to repro it sometimes.</p>
  
  <p>Our setup has NTLM auth, self-signed cert and self-hosted with OWIN/Katana. All written using .Net.</p>
  
  <p><strong>It only happens (so far) on VMs, we have not sen the problem using physical machines, although some of those VMs are really powerful</strong></p>
  
  <p>This is my code:</p>
  
  <p><strong>Client</strong></p>
  
  <pre><code>public Guid Upload(string filePath, Guid taskId)
  {
      if (string.IsNullOrEmpty(filePath)) { throw new ArgumentException("Value cannot be empty.", "filePath"); }
  
      var key = Guid.Empty;
      var fileInfo = new System.IO.FileInfo(filePath);
  
      using (var fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Open))
      {
          var content = new StreamContent(fileStream);
          content.Headers.Add("TaskId", taskId.ToString());
          content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
          content.Headers.ContentDisposition.FileName = fileInfo.Name;
          content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
          content.Headers.ContentLength = fileInfo.Length;
  
          key = HttpClient.PostGet&lt;Guid&gt;(content, "https://localhost:1234/Files/Upload");
      }
  
      return key;
  }
  
  public T PostGet&lt;T&gt;(string url, HttpContent content, IDictionary&lt;string, string&gt; headers)
  {
      using (var client = httpClient) // &lt;-- look below to check how we build this
      {
          client.AddHeaders(headers);
          HttpResponseMessage response = null;
  
          try
          {
              response = client.PostAsync(url, content).Result;
  
              ensureSuccessStatusCode(response);
  
              var jsonResult = response.Content.ReadAsStringAsync().Result;
              var obj = Deserialize&lt;T&gt;(jsonResult);
  
              return obj;
          }
          finally
          {
              if (response != null)
              {
                  response.Dispose();
              }
          }
      }
  }
  
  private System.Net.Http.HttpClient httpClient
  {
      get
      {
          System.Net.Http.HttpClient client = null;
  
          if (authenticationEnabled)
          {
              if (credentials == null)
              {
                  client = new System.Net.Http.HttpClient(new CertValidatingWebRequestHandler()
                  {
                      UseDefaultCredentials = true
                  });
              }
              else
              {
                  client = new System.Net.Http.HttpClient(new CertValidatingWebRequestHandler()
                  {
                      Credentials = credentials
                  });
              }
          }
          else
          {
              client = new System.Net.Http.HttpClient();
          }
  
          client.Timeout = TimeSpan.FromMilliseconds(TimeOutInMilliseconds);
          return client;
      }
  }
  
  public class CertValidatingWebRequestHandler : WebRequestHandler
  {
      public CertValidatingWebRequestHandler()
      {
          this.ServerCertificateValidationCallback = ValidateRemoteCert;
      }
  
      private bool ValidateRemoteCert(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyErrors)
      {
          return true;
      }
  }
  </code></pre>
  
  <p><strong>SERVER</strong></p>
  
  <pre><code>[HttpPost]
  [Route("Upload")]
  public async Task&lt;IHttpActionResult&gt; Upload()
  {
      return await upload(Guid.Empty);
  }
  
  private async Task&lt;IHttpActionResult&gt; upload(Guid appendToKey)
  {
      if (Request.Content.Headers.ContentType.MediaType.Equals("application/octet-stream", StringComparison.OrdinalIgnoreCase))
      {
          var taskId = Guid.Empty;
  
          if (Request.Headers.Contains("TaskId"))
          {
              var taskIdValue = Request.Headers.GetValues("TaskId").FirstOrDefault();
              taskId = new Guid(taskIdValue);
          }
  
          var fileName = Request.Content.Headers.ContentDisposition.FileName;
          fileName = fileName.Trim(' ', '"');
  
          if (string.IsNullOrEmpty(fileName))
          {
              throw new HttpResponseException(HttpStatusCode.BadRequest);
          }
  
          var key = Guid.NewGuid();
          var directoryPath = string.Empty;
  
          if (appendToKey == Guid.Empty)
          {
              directoryPath = createStorageDirectory(key);
          }
          else
          {
              var fileInfo = fileStorage.GetFileInfo(appendToKey);
  
              if (fileInfo == null)
              {
                  throw new Exception(string.Format("File with key {0} was not found.", appendToKey));
              }
  
              directoryPath = fileInfo.Path;
          }
  
          var filePath = fileSystem.Combine(directoryPath, fileName);
  
          using (var httpStream = await Request.Content.ReadAsStreamAsync())
          {
              using (var fileStream = new FileStream(filePath, FileMode.CreateNew))
              {
                  await httpStream.CopyToAsync(fileStream).ContinueWith(t =&gt;
                  {
                      try
                      {
                          handleResponse(key, directoryPath, fileName, appendToKey, taskId, t);
                      }
                      catch (Exception e)
                      {
                          deleteStorageFolder(key);
  
                          logger.Log(LogType.Error, e);
                          throw;
                      }
                  });
              }
          }
  
          return Ok(key);
      }
      else
      {
          throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
      }
  }
  </code></pre>
  
  <p><strong>FULL ERROR</strong></p>
  
  <pre><code>System.AggregateException: One or more errors occurred. ---&gt; System.NotSupportedException: The stream does not support concurrent IO read or write operations.
         at System.Net.ConnectStream.InternalWrite(Boolean async, Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
         at System.Net.ConnectStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
         at System.Net.Http.StreamToStreamCopy.TryStartWriteSync(Int32 bytesRead)
         at System.Net.Http.StreamToStreamCopy.BufferReadCallback(IAsyncResult ar)
         --- End of inner exception stack trace ---
      ---&gt; (Inner Exception #0) System.NotSupportedException: The stream does not support concurrent IO read or write operations.
         at System.Net.ConnectStream.InternalWrite(Boolean async, Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
         at System.Net.ConnectStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
         at System.Net.Http.StreamToStreamCopy.TryStartWriteSync(Int32 bytesRead)
         at System.Net.Http.StreamToStreamCopy.BufferReadCallback(IAsyncResult ar)&lt;---
  </code></pre>
  
  <p>Sorry for the long post, but i figured the more info the better would be for you.</p>
  
  <p>I'm trying to disable auth and certs to isolate the issue even further. I'll update later.</p>
  
  <p>Thanks in advance. Any help/Suggestion/Idea is more than welcome!!!!</p>