假设我有一个由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;
}
Run Code Online (Sandbox Code Playgroud)
在调用的第一行中,我调用了Client.GetAsync我的API。在我的API中,我可以正确地接收到调用,并且可以通过User对象正确返回Ok,或者返回其他代码。有用。我的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;
}
Run Code Online (Sandbox Code Playgroud)
没有等待的相同代码我没有问题。我的代码一直运行到下一步。证明我的API不是问题。
很明显,这是与等待/异步相关的问题。我必须做错什么,但是呢?你能帮助我吗?与调试器有关吗?
有关更多信息,这里是我的代码之前的图片
然后单击下一步。请注意,我的调用堆栈为空,并且代码仍在运行。
根据要求,这里是我称为登录名的代码。我只是在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
Run Code Online (Sandbox Code Playgroud)
我只是在Sub之前添加了异步字,并更改了_authService.Login(用户名,密码)。结果由await _authService.Login(用户名,密码)
一般指导是“不要阻止异步代码”。这是异步编程的最佳实践之一。
阻塞异步代码是不好的,因为默认情况下,它await通过捕获“上下文”来工作,并async在该上下文中恢复执行该方法。UI上下文是一种上下文,它使async方法恢复在UI线程上执行。
因此,您看到的死锁是由阻塞UI线程引起的。代码先调用该async方法,然后阻塞UI线程,直到该async方法完成。然而,await在该async方法中捕获的UI背景,所以它正在等待UI线程是免费的,才能够完成。UI线程正在等待async方法,而该async方法正在等待UI线程:死锁。
您的修复工作成功的原因是,不再等待该async方法阻止UI线程,因此不再有死锁。
| 归档时间: |
|
| 查看次数: |
87 次 |
| 最近记录: |