如何解决是否使用带有异步Task的ConfigureAwaitfalse和await传播异常?
我感觉自己对异步等待编程非常了解,但是今天发生的事情使我感到困惑。我一直在寻找这个问题的答案已有一段时间,但在任何地方都找不到。我已经阅读了很多有关异步等待编程的内容,但是我虚弱的头脑无法理解这种特定情况下到底发生了什么。
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);
}
在GetServerStatusAsync中,我已经尝试尝试捕获所有内容,因为我想在那里处理异常。我调用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);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。