微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是否使用带有异步Task的ConfigureAwaitfalse和await传播异常?

如何解决是否使用带有异步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);
}

我在代码段中添加了2条注释作为指针,但是基本思想是:

在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 举报,一经查实,本站将立刻删除。