简体   繁体   English

在异步方法和正常返回方法之间共享类变量

[英]sharing class variable between async method and normal return method

here is my class, have a async method and get method 这是我的课,有一个异步方法和获取方法

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";
    }

the token = await reader.ReadToEndAsync(); 令牌=等待reader.ReadToEndAsync(); can't set the class variable or maybe set after getToken was returned, anyone know how to deal with this situation? 无法设置类变量或返回getToken之后设置,有人知道如何处理这种情况吗?

By calling: 通过致电:

this.login(url);

You are firing and forgetting the async call. 您正在触发并忘记了异步调用。

You need to make the containing function async and await the login call to finish 您需要使包含函数异步并等待login调用完成

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

Do not use this.login(url).Wait() . 不要使用this.login(url).Wait()

Finally 最后

public async void login (string url)

async void is used for event handlers, it should be this: async void用于事件处理程序,应该是这样的:

public async Task login (string url)

IMHO 恕我直言

I believe this class has a too many responsibilities. 我相信这堂课的职责太多了。 It shouldn't be used to retrieve and store the token. 它不应该用于检索和存储令牌。 One would assume you have some kind of caching layer in your application (it could just be memory). 可以假设您的应用程序中有某种缓存层(可能只是内存)。

Therefore, I would prefer logic like: 因此,我更喜欢这样的逻辑:

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]);

The cache could just be a singleton class with a dictionary... cache可能只是带有字典的单例类。

The new Task<string> login(string url) method would now return the token at the bottom, rather than just setting a private field: 现在,新的Task<string> login(string url)方法将在底部返回令牌,而不仅仅是设置私有字段:

return await responseContent.ReadAsStringAsync();

This logic would then make it easier for you to add layers in and around the login if needs be without making the code hard to reason about. 如果需要,这种逻辑将使您更轻松地在登录名中及其周围添加层,而又无需使代码难以推理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM