c# - 是否使用带有异步任务和等待的 ConfigureAwait(false) 传播异常?
问题描述
我感觉我对异步等待编程有很好的把握,但是今天发生的事情让我感到困惑。我一直在寻找这个问题的答案一段时间,但无法在任何地方找到它。我已经阅读了很多关于异步等待编程的内容,但是我虚弱的头脑无法理解在这个特定场景中到底发生了什么。
我有这两种方法:
public async Task<IEnumerable<ServerStatus>> GetServersStatusAsync()
{
var serverStatuses = new List<ServerStatus>();
try
{
ServerStatusRequest request = new ServerStatusRequest();
var serverStatusResponse = await GetAsync<ServerStatusResponse>(request).ConfigureAwait(false);
}
// I would expect the exception thrown from GetAsync to be caught here. But it doesn't always do that.
catch (Exception ex)
{
_log.Error("Failed to retrieve server statuses.", ex);
}
return serverStatuses;
}
和
private async Task<T> GetAsync<T>(IRequest request)
{
string respString = string.Empty;
try
{
var requestUrl = request.GetQueryString(_apiToken);
_log.Debug($"Sending a request to {requestUrl}");
CancellationTokenSource tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(_timeoutInSec));
//This call can throw an exception. It will always get caught inside this current try catch,
//but if after the await we are continuing on a different thread,
//the re-thrown/propagated exception is not caught by the calling method.
var response = await _client.GetAsync(requestUrl, tokenSource.Token).ConfigureAwait(false);
if (response.IsSuccessStatusCode || response.StatusCode == HttpStatusCode.BadRequest)
{
respString = await response.Content.ReadAsStringAsync();
var deserializedObject = JsonConvert.DeserializeObject<T>(respString);
return deserializedObject;
}
}
catch (Exception ex) when (ex is JsonReaderException || ex is JsonSerializationException)
{
throw new JsonSerializationException($"Failed to deserialize {respString}", ex) { Source = respString };
}
return default(T);
}
我在代码片段中添加了 2 条注释作为指针,但基本思想是:
在 GetServerStatusAsync 中,我用 try catch 包装了所有内容,因为我想在那里处理异常。我调用 GetAsync,它等待使用 ConfigureAwait(false) 调用 HttpClient.GetAsync。如果我们不再在初始线程/上下文中,来自 HttpClient.GetAsync 的调用返回异常时,它可以在我的 GetAsync 方法中被捕获,但不会传播到 GetServerStatusAsync。如果我删除 ConfigureAwait(false),它总是会像我预期的那样向下传播,但使用 ConfigureAwait(false),它更像是 50/50。
我的代码或我对异步等待的理解是否存在灾难性问题?
任何帮助深表感谢。
编辑:根据评论中的请求,我添加了一个简化版本的调用 GetServersStatusAsync 的方法以及我如何调用该方法(以一种火而忘记的方式,但 Login 是用 try catch 包装的,所以不应该是大事件)。
public async Task Login(Action<LoginResult> callback = null)
{
LoginResult result = new LoginResult() { Success = false };
try
{
var serverStatus = await GetServersStatusAsync();
if (serverStatus.Any())
{
result.Success = true;
callback?.Invoke(result);
return;
}
}
catch (Exception ex)
{
result.Message = Strings.UnknownException;
_log.Error("Login failed due to unexpected exception", ex);
}
callback?.Invoke(result);
}
_restClient.Login(OnLoginResponse);
解决方案
推荐阅读
- javascript - 延迟加载 amchart 不会在向下滚动时呈现
- json - 无法将 Json 数组解码为列表
并得到错误类型'_InternalLinkedHashMap ' 不是类型 'List 的子类型 ' - android - 对复合对象的 LiveData 的更改
- c++ - C ++更改for循环的条件评估
- hibernate - Hibernate:超类映射到子类中的@UniqueConstraint
- node.js - 为什么我的函数在命令行中运行两次但在 vscode 中没有
- java - 学校 Java 密室逃脱计划
- python - 高维高斯平均
- model-view-controller - 使用 dropzone 使用 mvc webapi 上传图像
- c# - Spreadsheets.Get() 请求总是返回 500