我正在开发一个使用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循环中返回就好了?
答案 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中的数据 消费它的客户。