首页 > 解决方案 > 附加到之前启动的异步进程

问题描述

所以我有一个使用用户令牌的应用程序。用户只能在 1 台设备上登录(登录后以前的令牌过期)。所以我想出了一个想法来缓存一些数据。所以我创建了一个单例的 CacheManager。

CacheManager 有一个字典,其中包含以前获取的数据。

所以这里有一个例子:

/// <summary>
/// Tries to get Global settings data from the cache. If it is not present - asks ServiceManager to fetch it.
/// </summary>
/// <returns>Global setting object</returns>
public async Task<GlobalSettingsModel> GetGlobalSettingAsync()
{
    GlobalSettingsModel result;

    if (!this.cache.ContainsKey("GlobalSettings"))
    {
        result = await ServiceManager.Instance.RequestGlobalSettingAsync();
        if (result != null)
        {
            this.cache.Add("GlobalSettings", result);
        }

        // TODO: Figure out what to do in case of null
    }

    return (GlobalSettingsModel)this.cache["GlobalSettings"];
}

所以问题是,我该如何修改这个方法来处理这种情况:

例如,我从服务器调用的方法比用户导航到需要数据的页面的工作时间更长,我想显示一个加载指示器并在实际收到数据时隐藏它。

为什么我需要它,我们有 2 个页面 - ExtendedSplashScreen 和 UpdatesPage 用户可以快速跳过它们(1s)或留下来阅读有趣的信息(比如说 1m)。在这段时间里,我已经开始获取 GetGlobalSetting 以便在他到达 LoginPage 时结束该过程或下载至少一些东西(以最小化等待用户)。

在我的 ExtendedSplashScreen 上,我启动了:

CacheManager.Instance.GetGlobalSettingAsync();

出于测试目的,我修改了 ServiceManager 方法:

/// <summary>
/// Fetches the object of Global Settings from the server
/// </summary>
/// <returns>Global setting object</returns>
public async Task<GlobalSettingsModel> RequestGlobalSettingAsync()
{
    await Task.Delay(60000);

    // Request and response JSONs are here, because we will need them to be logged if any unexpected exceptions will occur

    // Response JSON
    string responseData = string.Empty;

    // Request JSON
    string requestData = JsonConvert.SerializeObject(new GlobalSettingsRequestModel());

    // Posting list of keys that we want to get from GlobalSettings table
    HttpResponseMessage response = await client.PostAsync("ServerMethod", new StringContent(requestData, Encoding.UTF8, "application/json"));

    // TODO: HANDLE ALL THE SERVER POSSIBLE ERRORS

    Stream receiveStream = await response.Content.ReadAsStreamAsync();
    StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);

    // Read the response data
    responseData = readStream.ReadToEnd();

    return JsonConvert.DeserializeObject<GlobalSettingsResponseModel>(responseData).GlobalSettings;
}

因此,当用户进入 LoginPage 时,我会执行以下操作:

// The await is here because there is no way without this data further
GlobalSettingsModel settings = await CacheManager.Instance.GetGlobalSettingAsync();

在这里,如果数据已经下载,我想从缓存中获取数据,或者 CacheManager 会在下载完成后立即返回数据。

标签: c#async-await

解决方案


一种方法是缓存Task<GlobalSettingsModel>而不是缓存GlobalSettingsModel本身。当您从缓存中获取它时,您可以检查它是否已完成,然后等待或相应地使用其结果。


推荐阅读