我在xamarin表单项目中使用HttpClient
该类已记录,但我找不到任何有关其方法可能引发异常的文档.
例如,GetAsync方法没有关于可能的异常的任何文档.但我认为它会抛出,例如当服务器无法访问时.
这个类可能会抛出一些例外列表吗?
给出以下代码:
var cts = new CancellationTokenSource();
try
{
// get a "hot" task
var task = new HttpClient().GetAsync("http://www.google.com", cts.Token);
// request cancellation
cts.Cancel();
await task;
// pass:
Assert.Fail("expected TaskCanceledException to be thrown");
}
catch (TaskCanceledException ex)
{
// pass:
Assert.IsTrue(cts.Token.IsCancellationRequested,
"expected cancellation requested on original token");
// fail:
Assert.IsTrue(ex.CancellationToken.IsCancellationRequested,
"expected cancellation requested on token attached to exception");
}
Run Code Online (Sandbox Code Playgroud)
我希望ex.CancellationToken.IsCancellationRequested是true在catch块内,但事实并非如此.我误会了什么吗?
.net c# async-await cancellationtokensource dotnet-httpclient
HttpClient有一个内置超时功能(尽管都是异步的,即超时可以被认为是与http请求功能正交,因此可以由通用异步实用程序处理,但是除此之外)当超时启动时,它会抛出一个TaskCanceledException(包含在内) a AggregateException).
TCE包含CancellationToken等于的CancellationToken.None.
现在,如果我提供HttpClient了CancellationToken我自己的一个并使用它来取消操作完成(或超时),我得到完全相同TaskCanceledException,再次使用CancellationToken.None.
通过仅查看抛出的异常,还有一种方法可以确定超时是否取消了请求,而不必让我自己CancellationToken可以访问检查异常的代码?
PS这可能是一个错误,并CancellationToken以某种方式错误地修复CancellationToken.None?在取消使用自定义CancellationToken的情况下,我希望TaskCanceledException.CancellationToken等于该自定义令牌.
编辑
为了使问题更加清晰,通过访问原始文件CancellationTokenSource,很容易区分超时和用户取消:
origCancellationTokenSource.IsCancellationRequested == true
CancellationToken从异常中获取但是给出了错误的答案:
((TaskCanceledException)e.InnerException).CancellationToken.IsCancellationRequested == false
这是一个最小的例子,由于受欢迎的需求:
public void foo()
{
makeRequest().ContinueWith(task =>
{
try
{
var result = task.Result;
// do something with the result;
}
catch (Exception e)
{
TaskCanceledException innerException = e.InnerException as TaskCanceledException;
bool …Run Code Online (Sandbox Code Playgroud) 您好我正在使用类似这样的HttpClient:
public static Task<string> AsyncStringRequest(string url, string contentType)
{
try
{
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(contentType));
return client.GetStringAsync(url).ContinueWith(task => {
return task.Result;
});
}
catch (AggregateException ex)
{
throw ex;
}
catch (WebException ex)
{
throw ex;
}
catch (Exception ex)
{
throw ex;
}
}
Run Code Online (Sandbox Code Playgroud)
但我处理异常时遇到困难.我添加了额外的catch块只是为了尝试并逐步抛出,但没有任何断点被捕获到任何catch块中.我意识到使用Task,异常可能发生在与调用者不同的线程上,因此异常包含在聚合容器中,但我不确定处理这些异常的最佳方法是什么.
例如,我向Web服务发出请求,并在请求中指定了特定的无效参数,并抛出异常.我希望我能够捕获聚合异常,并查看innerexceptions以找出请求失败的原因并返回友好消息.
所以我的问题是,捕获这些聚合异常并处理它们的最佳方法是什么?
我FileResult : IHttpActionResult为api调用创建了一个webapi返回类型.FileResult从另一个URL下载文件,然后将流返回给客户端.
最初我的代码有using如下声明:
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
try
{
HttpResponseMessage response;
using (var httpClient = new HttpClient())
{
response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new System.Net.Http.StreamContent(
await httpClient.GetStreamAsync(this.filePath))
};
}
return response;
}
catch (WebException exception)
{...}
}
Run Code Online (Sandbox Code Playgroud)
然而,这会间歇性地导致TaskCanceledException.我知道如果在异步调用完成之前处理了HttpClient,Task的状态将变为取消.但是因为我使用了await:Content = new System.Net.Http.StreamContent(await httpClient.GetStreamAsync(this.filePath))这应该可以防止HttpClient在任务完成过程中被丢弃.
为什么该任务被取消?这不是因为超时,因为这发生在最小的请求上,并不总是发生在大请求上.
当我删除using语句时代码正常工作:
public async Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
try
{
HttpResponseMessage response;
var httpClient = new HttpClient();
response = new …Run Code Online (Sandbox Code Playgroud) c# using-statement httpclient task-parallel-library asp.net-web-api
我有一个Json,其中包含一个存储base64编码字符串的数据字段.这个Json被序列化并发送给客户端.
在客户端,newtonsoft json.net反序列化器用于返回Json.但是,如果数据字段变大(~400 MB),则解串器将抛出内存不足异常:数组维度超出支持的范围.我还在Task-Manager中看到,内存消耗确实快速增长.
任何想法为什么会这样?是否有json字段的最大大小?
代码示例(简化):
HttpResponseMessage responseTemp = null;
responseTemp = client.PostAsJsonAsync(client.BaseAddress, message).Result;
string jsonContent = responseTemp.Content.ReadAsStringAsync.Result;
result = JsonConvert.DeserializeObject<Result>(jsonContent);
Run Code Online (Sandbox Code Playgroud)
结果类:
public class Result
{
public string Message { get; set; }
public byte[] Data { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
更新:
我认为我的问题不是序列化程序,而只是试图在内存中处理这么大的字符串.在我将字符串读入内存时,应用程序的内存消耗会爆炸.该字符串上的每个操作都是相同的.目前,我认为我必须找到一种方法来处理流并立即停止将所有内容读入内存.
几乎在过去24小时内,由于调用ResumeableUpload的UploadAsync,我一直在接收TaskCanceledExceptions.上传可能有90%的时间失败.我正在将视频上传到youtube.
我使用的是早期版本的google-apis(1.4),所以我尝试升级到1.5的最新nuget包,但问题没有改变.
知道可能会发生什么吗?我很困惑,因为我有时没有改变我的代码......
The stack trace is as follows:
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at Google.Apis.Upload.ResumableUpload`1.<Upload>d__0.MoveNext() in c:\code.google.com\google-api-dotnet-client\default_3\Tools\Google.Apis.Release\bin\Debug\output\default\Src\GoogleApis\Apis\[Media]\Upload\ResumableUpload.cs:line 362
Run Code Online (Sandbox Code Playgroud) 出于某种原因,当 anOperationCanceledException被抛出到 内时IDataflowBlock,块不会将此异常传播到其IDataflowBlock.Completion任务。运行下面的代码示例会返回一个意外的IDataflowBlock.Completion.Status == TaskStatus.RanToCompletion.
但是,如果块中抛出的异常类型更改为 an ArgumentNullException,则IDataflowBlock.Completion.Status更改TaskStatus.Faulted和 异常将保存在其InnerException属性中。
任何想法为什么OperationCanceledException被吞下?
[TestFixture]
public class TplDataBlockExceptionTest
{
[Test]
public void ShouldThrowException()
{
// Arrange
var block = new TransformBlock<int, string>(i =>
{
throw new OperationCanceledException();
return i.ToString();
});
// Act
block.Post(1);
block.Complete();
try
{
block.Completion.Wait();
}
catch (Exception)
{
// ignored
}
// Assert
Assert.That(block.Completion.IsFaulted);
}
}
Run Code Online (Sandbox Code Playgroud) 注册服务:
var host = new HostBuilder().ConfigureServices(services =>
{
services.AddHttpClient<Downloader>(client =>
{
client.Timeout = TimeSpan.FromSeconds(1); // -- T1
})
.AddPolicyHandler(HttpPolicyExtensions
.HandleTransientHttpError()
.Or<HttpRequestException>()
.WaitAndRetryAsync(Backoff.DecorrelatedJitterBackoffV2(
TimeSpan.FromSeconds(5), // -- T2
retryCount: 3)))
.AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(10)) // -- T3
.AddPolicyHandler(HttpPolicyExtensions
.HandleTransientHttpError()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30))); // -- T4
services.AddTransient<Downloader>();
}).Build();
Run Code Online (Sandbox Code Playgroud)
实施Downloader:
class Downloader
{
private HttpClient _client;
public Downloader(IHttpClientFactory factory)
{
_client = factory.CreateClient();
}
public void Download(List<Uri> links)
{
await Parallel.ForEachAsync(
links,
async (link, _cancelationToken) =>
{
await _client.GetStreamAsync(uri, _cancellationToken);
});
}
}
Run Code Online (Sandbox Code Playgroud)
在此伪代码中,我对超时之间的相关性以及如何/何时重新提交 HTTP 请求感到困惑。具体来说: …
c# ×8
httpclient ×3
.net ×2
timeout ×2
.net-core ×1
async-await ×1
base64 ×1
json.net ×1
polly ×1
rest ×1
tpl-dataflow ×1