如何在异步http请求任务之后只运行一次代码

时间:2018-06-11 18:02:07

标签: c# .net asynchronous

我正在开发一个使用requestAndParse()方法在线调用和请求数据的库。我想让库对用户快速多次查询服务器变得强大。

异步方法目前有两个部分。首先,它使用request = client.GetStringAsync从网址请求数据。然后它从request结果中解析该数据,并以结构的形式返回该数据。出于本示例的目的,我调用了结构Data

我已经有了通过将httprequest存储为变量来保护多个http请求的代码,并且只有在旧请求完成或不存在(null)时才实例化新请求。

然后下一部分解析数据。这是一个非常漫长的过程,我只想为每个httpRequest运行一次。但是,我现在设置代码的方式,即使只有一个http请求,解析部分也会每次运行requestAndParse()代码时运行。

代码类似于:

 class ServerRequester {
    private HttpClient = client;
    private Task<string> request = null;

    public async Task<Data> requestAndParse() {
       if (request == null || request.IsCompleted()) {
           // Instantiate new request if there is nothing running already
           request = client.GetStringAsync(url);
        }
        // Wait for request
        this.response = await request;

        /**
         ** 
         ** parse data
         ** ...
         **/
         return data;
    }
}

问题是,如果我以非常快的速度调用requestAndParse() 10次,我将不得不从同一个http请求中解析相同的数据10次。如果解析成本很高,或者解析存储状态以供以后使用,则意味着我将添加相同的数据10次。有没有办法让这段代码只进行一次,但在for循环中返回就好了?

2 个答案:

答案 0 :(得分:0)

不是存储代表服务器查询原始数据的Task<string>,而是缓存代表服务器查询原始数据并解析它的Task<Data>

答案 1 :(得分:0)

看起来您希望在已经有正在进行的请求时避免发出新请求。控制它的一种方法是使用lock

class ServerRequester {
    private readonly Object obj = new Object();
    private object Data; // I don't know what is the type of Data

    public async Task<Data> requestAndParse()
    {
        lock (this.obj)
        {
            if (this.Data == null)
            {
                // Wait for request
                this.response = await client.GetStringAsync(url);

                /**
                ** 
                ** parse data
                ** ...
                **/
            }
        }
        return this.Data;
    }
}

如果在第一个呼叫仍然正在解析或等待 http呼叫时对同一个ServerRequester实例进行了第二次呼叫,则它将在lock语句中停止。在第一次呼叫中释放锁定后,第二次呼叫(以及任何其他下一次呼叫)将检查this.Data是否与null不同(这意味着您已经解析了数据)。如果不是,则只返回缓存的数据。否则,它将进行http调用并执行请求。

如果要缓存数据并锁定链接的调用,无论ServerRequester实例正在进行调用,请使obj静态。

  

作为旁注,如果您可以控制后端API,则可以   考虑到你可能有很多,也可以缓存API中的数据   消费它的客户。