"Cannot close stream until all bytes are written" WriteAsync 操作取消时
"Cannot close stream until all bytes are written" when WriteAsync operation is Cancelled
当取消对 HttpWebRequest.GetRequestStream()
创建的流的 WriteAsync
操作时,我收到一个 WebException,其中包含以下消息:
Cannot close stream until all bytes are written
当我使用 CancellationToken
取消操作时,如何清理我的 HttpWebRequest
和流?
这是我的工作代码的一部分(我为此 post 清理了一些 headers 所以请求可能格式不正确):
public async Task<bool> UploadAsync(FileInfo fi, CancellationToken ct, IProgress<int> progress = null)
{
FileStream fs = new FileStream(fi.FullName, FileMode.Open);
int bufferSize = 1 * 1024 * 1024;
byte[] buffer = new byte[bufferSize];
int len;
long position = fs.Position;
long totalWrittenBytes = 0;
HttpWebRequest uploadRequest = null;
Stream putStream = null;
try
{
while ((len = fs.Read(buffer, 0, buffer.Length)) > 0)
{
uploadRequest = (HttpWebRequest)WebRequest.Create("http://myuploadUrl");
uploadRequest.Method = "PUT";
uploadRequest.AddRange(position, position + len - 1);
uploadRequest.ContentLength = len;
putStream = uploadRequest.GetRequestStream();
int posi = 0;
int bytesLeft = len;
int chunkSize;
while (bytesLeft > 0)
{
chunkSize = Math.Min(25 * 1024, bytesLeft); //25KB
//HERE IS the WriteAsync part that is being cancelled
await putStream.WriteAsync(buffer, posi, chunkSize, ct);
bytesLeft -= chunkSize;
posi += chunkSize;
totalWrittenBytes += chunkSize;
if (progress != null)
progress.Report((int)(totalWrittenBytes * 100 / fs.Length));
}
putStream.Close();
putStream = null;
position = fs.Position;
var putResponse = (HttpWebResponse)uploadRequest.GetResponse();
putResponse.Close();
uploadRequest = null;
}
//putStream.Write(buffer, 0, len);
}
catch (OperationCanceledException ex)
{
if (putStream != null)
{
putStream.Flush();
putStream.Close();//WebException occur here: Cannot close stream until all bytes are written.
}
return false;
}
finally{
fs.Close();
}
return true;
}
我终于抓住了 WebException
因为 post 请求必须写入预期的字节数 (ContentLength
属性)
这是我的最后收获
catch (OperationCanceledException ex)
{
try
{
if (putStream != null)
putStream.Dispose();
}
catch (WebException) { }
return false;
}
finally{
fs.Close();
}
也许我不确定是否应该尝试处理流?
当取消对 HttpWebRequest.GetRequestStream()
创建的流的 WriteAsync
操作时,我收到一个 WebException,其中包含以下消息:
Cannot close stream until all bytes are written
当我使用 CancellationToken
取消操作时,如何清理我的 HttpWebRequest
和流?
这是我的工作代码的一部分(我为此 post 清理了一些 headers 所以请求可能格式不正确):
public async Task<bool> UploadAsync(FileInfo fi, CancellationToken ct, IProgress<int> progress = null)
{
FileStream fs = new FileStream(fi.FullName, FileMode.Open);
int bufferSize = 1 * 1024 * 1024;
byte[] buffer = new byte[bufferSize];
int len;
long position = fs.Position;
long totalWrittenBytes = 0;
HttpWebRequest uploadRequest = null;
Stream putStream = null;
try
{
while ((len = fs.Read(buffer, 0, buffer.Length)) > 0)
{
uploadRequest = (HttpWebRequest)WebRequest.Create("http://myuploadUrl");
uploadRequest.Method = "PUT";
uploadRequest.AddRange(position, position + len - 1);
uploadRequest.ContentLength = len;
putStream = uploadRequest.GetRequestStream();
int posi = 0;
int bytesLeft = len;
int chunkSize;
while (bytesLeft > 0)
{
chunkSize = Math.Min(25 * 1024, bytesLeft); //25KB
//HERE IS the WriteAsync part that is being cancelled
await putStream.WriteAsync(buffer, posi, chunkSize, ct);
bytesLeft -= chunkSize;
posi += chunkSize;
totalWrittenBytes += chunkSize;
if (progress != null)
progress.Report((int)(totalWrittenBytes * 100 / fs.Length));
}
putStream.Close();
putStream = null;
position = fs.Position;
var putResponse = (HttpWebResponse)uploadRequest.GetResponse();
putResponse.Close();
uploadRequest = null;
}
//putStream.Write(buffer, 0, len);
}
catch (OperationCanceledException ex)
{
if (putStream != null)
{
putStream.Flush();
putStream.Close();//WebException occur here: Cannot close stream until all bytes are written.
}
return false;
}
finally{
fs.Close();
}
return true;
}
我终于抓住了 WebException
因为 post 请求必须写入预期的字节数 (ContentLength
属性)
这是我的最后收获
catch (OperationCanceledException ex)
{
try
{
if (putStream != null)
putStream.Dispose();
}
catch (WebException) { }
return false;
}
finally{
fs.Close();
}
也许我不确定是否应该尝试处理流?