如何复制HttpContent async和cancelable?
我正在使用HttpClient.PostAsync()
,响应是一个HttpResponseMessage
。 它的Content属性是HttpContent
类型,它有一个CopyToAsync()
方法。 不幸的是,这是不可取消的。 有没有办法将响应复制到Stream
并传递CancellationToken
?
我没有CopyToAsync()
! 如果有解决方法,那就没问题了。 就像读取几个字节一样,检查是否取消,继续阅读等等。
HttpContent.CreateContentReadStreamAsync()
方法看起来像是一个候选者。 很遗憾,我选择的个人资料无法使用此function。 还不清楚它是否会一次性读取所有数据并浪费大量内存。
注意:我在PCL中使用这个,目标是WP8,Windows Store 8,.NET 4.5,Xamarin.iOS和Xamarin.Android
我相信这应该有效:
public static async Task DownloadToStreamAsync(string uri, HttpContent data, Stream target, CancellationToken token) { using (var client = new HttpClient()) using (var response = await client.PostAsync(uri, data, token)) using (var stream = await response.Content.ReadAsStreamAsync()) { await stream.CopyToAsync(target, 4096, token); } }
请注意, ReadAsStreamAsync
调用CreateContentReadStreamAsync
,对于流响应, ReadAsStreamAsync
返回基础内容流而不将其缓冲到内存中。
您无法取消不可取消的操作。 请参阅如何取消不可取消的异步操作? 。
但是,您可以使用WithCancellation
使代码流的行为就像基础操作被取消WithCancellation
。
public static Task WithCancellation (this Task task, CancellationToken cancellationToken) { return task.IsCompleted ? task : task.ContinueWith( completedTask => completedTask.GetAwaiter().GetResult(), cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); }
用法:
await httpContent.PostAsync(stream).WithCancellation(new CancellationTokenSource(1000).Token);
HttpClient.CancelPendingRequests
应该取消所有挂起的操作。 我还没有validation是否也适用于CopyToAsync
。 随意试试:
public static async Task CopyToAsync( System.Net.Http.HttpClient httpClient, System.Net.Http.HttpContent httpContent, Stream stream, CancellationToken ct) { using (ct.Register(() => httpClient.CancelPendingRequests())) { await httpContent.CopyToAsync(stream); } }
[UPDATE]已经validation:遗憾的是,这并没有取消HttpContent.CopyToAsync
。 我保留了这个答案,因为模式本身可能对取消HttpClient
上的其他操作很有用。