Понимание инструкции асинхронного ожидания во время запроса HttpClient - PullRequest
0 голосов
/ 28 февраля 2019

Допустим, у меня есть решение, состоящее из 2 проектов.Старый классический проект WinForm.В этом старом проекте у меня есть окно входа.При нажатии «ОК» в этом окне входа в систему я запускаю событие, которое вызовет REST API.Оба приложения запускаются одновременно в режиме отладки.

Где-то в моем коде у меня есть этот код:

public async Task<User> Login(string username, string password)
{
    HttpResponseMessage response = await Client.GetAsync($"api/Login?login={username}&password={password}");
    if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
        return new User();
    response.EnsureSuccessStatusCode();
    var userDto = await response.Content.ReadAsAsync<UserDto>();
    var user = userDto.ToUser();
    return user;
}

В первой строке, когда я вызываю Client.GetAsync, я вызываю мойAPI.В моем API я правильно получаю вызов, и я правильно возвращаю Ok с моим объектом User, или я возвращаю другой код.Оно работает.Мой API работает.Но тогда ничего.Мой клиент никогда не продолжается.Кажется, Client.GetSync чего-то ждет.Я никогда не перехожу к следующему шагу, где я оцениваю StatusCode.

public async Task<User> Login(string username, string password)
{
    HttpResponseMessage response = Client.GetAsync($"api/Login?login={username}&password={password}").Result;
    if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
        return new User();
    response.EnsureSuccessStatusCode();
    var userDto = await response.Content.ReadAsAsync<UserDto>();
    var user = userDto.ToUser();
    return user;
}

Тот же код без ожидания у меня нет проблем.Мой код работает до следующего шага.Доказательство, что мой API не является проблемой.

Это ясно, что это проблема, связанная с await / async.Я должен сделать что-то не так, но что?Вы можете мне помочь?Это связано с отладчиком?

Для получения дополнительной информации вот изображение моего кода до

enter image description here

И после того, как я нажму наследующий шаг.Обратите внимание, что мой стек вызовов пуст, а код все еще выполняется.

enter image description here

В соответствии с запросом здесь указан код, по которому я вызываю логин.Я просто добавил асинхронное слово перед Sub и изменил _authService.Login (имя пользователя, пароль). Результат await _authService.Login (имя пользователя, пароль)

Я работаю сейчас.

Private Async Sub ButLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butLogin.Click
    DataProxies.SetToken()
    Dim _authService As IAuthenticationService = New AuthenticationService()


    Dim username As String = txtLogin.Text
    Dim password As SecureString = New NetworkCredential(String.Empty, txtPwd.Text).SecurePassword

    Dim auth As Tuple(Of Boolean, User) = Await _authService.Login(username, password)
    If (auth.Item1) Then
        Dim user As User = auth.Item2
        Name = $"{user.FirstName} {user.LastName}"
        ApiInformations.ApiToken = user.SessionToken
    End If
End Sub

1 Ответ

0 голосов
/ 28 февраля 2019

Я просто добавил асинхронное слово перед Sub и изменил _authService.Login (имя пользователя, пароль). Результат await _authService.Login (имя пользователя, пароль)

Общее руководство «Не блокировать асинхронный код» .Это один из рекомендаций по асинхронному программированию .

Блокировка асинхронного кода плохая, поскольку await по умолчанию захватывает «контекст» и возобновляет работувыполнение метода async в этом контексте.Одним контекстом является контекст пользовательского интерфейса, который заставляет метод async возобновить выполнение в потоке пользовательского интерфейса.

Таким образом, возникшая тупиковая ситуация была вызвана блокировкой потока пользовательского интерфейса.Код вызывал метод async, а затем блокировал поток пользовательского интерфейса до тех пор, пока метод async не завершился.Однако await в этом методе async захватил контекст пользовательского интерфейса, поэтому он ожидал освобождения потока пользовательского интерфейса до его завершения.Поток пользовательского интерфейса ожидал метод async, а метод async ожидал поток пользовательского интерфейса: взаимоблокировка.

Причина , с которой вы работали, заключается в том, что поток пользовательского интерфейса небольше заблокирован в ожидании метода async, поэтому тупиков больше нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...