在异步方法和普通返回方法之间共享类变量

时间:2017-02-06 16:20:05

标签: c# winforms asynchronous

这是我的类,有一个异步方法和get方法

class Webservice
{
    public string token;
    public async void login (string url)
    {
        Console.WriteLine(url);
        var client = new HttpClient();

        // Create the HttpContent for the form to be posted.
        string username = ConfigurationSettings.AppSettings["email"];
        string password = ConfigurationSettings.AppSettings["password"];

        var requestContent = new FormUrlEncodedContent(new[] {
                new KeyValuePair<string, string>("email", username),
                new KeyValuePair<string, string>("password", password),
        });

        // Get the response.
        HttpResponseMessage response = await client.PostAsync(url, requestContent);

        // Get the response content.
        HttpContent responseContent = response.Content;

        // Get the stream of the content.
        using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
        {
            // Write the output.
            //Console.WriteLine(await reader.ReadToEndAsync());
            token = await reader.ReadToEndAsync();

        }
    }


    public string getToken (string url)
    {
        this.login(url);
        Console.WriteLine(token);
        return token+"abc";
    }

token = await reader.ReadToEndAsync();无法设置类变量或者在返回getToken后设置,有人知道如何处理这种情况吗?

1 个答案:

答案 0 :(得分:2)

致电:

this.login(url);

您正在解雇并忘记异步通话。

您需要使包含函数异步并等待login调用完成

public async Task<string> getToken (string url)
{
    await this.login(url);
    Console.WriteLine(token);
    return token+"abc";
}

不要使用this.login(url).Wait()

最后

public async void login (string url)

async void用于事件处理程序,它应该是这样的:

public async Task login (string url)

IMHO

我相信这门课的责任太多了。它不应该用于检索和存储令牌。可以假设你的应用程序中有某种缓存层(它可能只是内存)。

因此,我更喜欢逻辑:

if (string.IsNullOrWhiteSpace(this.cache[TOKEN_KEY])) {
   this.cache[TOKEN_KEY] = await this.webservice.login(url);
}

// use the this.cache[TOKEN_KEY] here...
await this.anotherService.MakeRequest(this.cache[TOKEN_KEY]);

cache可能只是一个带字典的单例类......

新的Task<string> login(string url)方法现在会返回底部的令牌,而不仅仅是设置私有字段:

return await responseContent.ReadAsStringAsync();

如果需要,这个逻辑可以让你更容易在登录中和周围添加图层而不会使代码难以理解。