踩雷,前端一直卡在获取token中

发布于:2025-04-12 ⋅ 阅读:(74) ⋅ 点赞:(0)

问题:一直卡在var token = SecureStorage.Default.GetAsync("auth_token").Result;

 public VideoService()
 {
     _httpClient = new HttpClient();
     var token = SecureStorage.Default.GetAsync("auth_token");
 }

这是一个典型的同步等待异步操作导致的死锁问题。在 VideoService 构造函数中使用 .Result 来同步等待异步操作是不推荐的做法,这可能会导致死锁。

这个问题的根本原因是:

  1. 在构造函数中使用 SecureStorage.Default.GetAsync("auth_token").Result 会同步阻塞当前线程,等待异步操作完成

  2. 而 SecureStorage 的异步操作可能需要在 UI 线程上完成某些操作

  3. 如果这个构造函数是在 UI 线程上调用的,就会造成死锁:UI 线程在等待异步操作完成,而异步操作又需要 UI 线程才能完成

解决方案是:

  1. 将同步的令牌获取操作改为真正的异步操作

  2. 在构造函数中只初始化 HttpClient 实例

  3. 添加一个私有的异步方法 InitializeHttpClient() 来处理令牌获取和设置 Authorization 头

  4. 使用 async void 模式(仅适用于这种初始化场景)来启动异步操作但不阻塞构造函数

这样修改后,构造函数会立即返回,而令牌的获取和设置会在后台异步完成,避免了死锁问题。

需要注意的是,这种方法也有一个小缺点:如果用户立即调用 VideoService 的方法,可能会在令牌设置完成之前就发出请求。不过在实际应用中,通常在登录后会有一定的时间间隔再调用其他 API,所以这个问题不太可能发生。

如果您希望确保令牌一定设置好再使用,可以考虑以下两种方案:

  1. 将 VideoService 的构造函数也改为异步,并使用工厂模式创建实例

  2. 在每个公共方法中检查并确保令牌已设置

public VideoService()
{
    _httpClient = new HttpClient();
    InitializeHttpClient();
}

private async void InitializeHttpClient()
{
    try
    {
        // 从安全存储中获取认证令牌
        var token = await SecureStorage.Default.GetAsync("auth_token");
        if (!string.IsNullOrEmpty(token))
        {
            _httpClient.DefaultRequestHeaders.Authorization = 
                new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine($"初始化 HttpClient 时出错: {ex.Message}");
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到