Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用ConfigureAwait(false)和async Task和await传播异常吗?_C#_Asynchronous_Async Await_Configureawait - Fatal编程技术网

C# 使用ConfigureAwait(false)和async Task和await传播异常吗?

C# 使用ConfigureAwait(false)和async Task和await传播异常吗?,c#,asynchronous,async-await,configureawait,C#,Asynchronous,Async Await,Configureawait,我觉得我对异步等待编程有着很好的掌握,但今天发生的事情让我感到困惑。我已经寻找了一段时间的答案,但在任何地方都找不到。我已经读了很多关于异步等待编程的书,但是我虚弱的头脑无法理解在这个特定场景中到底发生了什么 我有两种方法: public async Task<IEnumerable<ServerStatus>> GetServersStatusAsync() { var serverStatuses = new List<ServerStatus>(

我觉得我对异步等待编程有着很好的掌握,但今天发生的事情让我感到困惑。我已经寻找了一段时间的答案,但在任何地方都找不到。我已经读了很多关于异步等待编程的书,但是我虚弱的头脑无法理解在这个特定场景中到底发生了什么

我有两种方法:

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;
}

如何调用
GetServersStatusAsync
?@TheodorZoulias我这样称呼它:var serverStatus=await GetServersStatusAsync();理想情况下,如果以异步方式抛出异常,则该异常将被抛出到某个
线程池
线程上,该线程本应执行等待线程的继续。在上述情况下,它必须异步抛出(在调用
await
之后),并且由于您正在附加ConfigureAwait(false),因此它不会被捕获到同一线程上下文中。更多信息:@SaiGummaluri是的,但是try块是上下文吗?我认为即使在不同的上下文中,它仍然可以捕获异常?@DainiusCerniauskas
回调有什么意义?.Invoke(result)
当您已经使用
async/wait
时<代码>等待将执行返回到原始同步上下文。如果从UI线程调用了
Login
,则只需调用
callback(result)
。如果必须使用
Invoke
,则表示您正在从后台线程调用
Login
。您可能是从
异步void
方法调用
Login
吗?如何调用
GetServersStatusAsync
?@TheodorZoulias我这样称呼它:var serverStatus=await GetServersStatusAsync();理想情况下,如果以异步方式抛出异常,则该异常将被抛出到某个
线程池
线程上,该线程本应执行等待线程的继续。在上述情况下,它必须异步抛出(在调用
await
之后),并且由于您正在附加ConfigureAwait(false),因此它不会被捕获到同一线程上下文中。更多信息:@SaiGummaluri是的,但是try块是上下文吗?我认为即使在不同的上下文中,它仍然可以捕获异常?@DainiusCerniauskas
回调有什么意义?.Invoke(result)
当您已经使用
async/wait
时<代码>等待将执行返回到原始同步上下文。如果从UI线程调用了
Login
,则只需调用
callback(result)
。如果必须使用
Invoke
,则表示您正在从后台线程调用
Login
。您是否正在从
async void
方法调用
Login
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);
}
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);