【发布时间】:2014-01-08 12:52:56
【问题描述】:
我正在将 SPARQL 查询作为异步请求发送到 SPARQL 端点,目前使用 dotNetRDF libraryDBpedia。虽然更简单的查询通常有效,但更复杂的查询有时会导致超时。
我正在寻找一种方法来处理超时,方法是在它们发生时捕获一些事件。
我使用SparqlRemoteEndpoint class 中的one of the asynchronous QueryWithResultSet overloads 发送查询。
如SparqlResultsCallback 所述,如果异步请求失败,state 对象将被替换为 AsyncError instance。这确实表明存在超时,但它似乎仅在请求发送后 10 分钟 才这样做。例如,当我的超时时间是 30 秒时,我想在 30 秒后知道请求是否成功。 (35 秒也可以,但你明白了。)
这是一个示例应用程序,它发送两个请求,第一个非常简单,很可能在超时(这里设置为 120 秒)内成功,而第二个相当复杂,很容易在 DBpedia 上失败:
using System;
using System.Collections.Concurrent;
using VDS.RDF;
using VDS.RDF.Query;
public class TestTimeout
{
private static string FormatResults(SparqlResultSet results, object state)
{
var result = new System.Text.StringBuilder();
result.AppendLine(DateTime.Now.ToLongTimeString());
var asyncError = state as AsyncError;
if (asyncError != null) {
result.AppendLine(asyncError.State.ToString());
result.AppendLine(asyncError.Error.ToString());
} else {
result.AppendLine(state.ToString());
}
if (results == null) {
result.AppendLine("results == null");
} else {
result.AppendLine("results.Count == " + results.Count.ToString());
}
return result.ToString();
}
public static void Main(string[] args)
{
Console.WriteLine("Launched ...");
Console.WriteLine(DateTime.Now.ToLongTimeString());
var output = new BlockingCollection<string>();
var ep = new SparqlRemoteEndpoint(new Uri("http://dbpedia.org/sparql"));
ep.Timeout = 120;
Console.WriteLine("Server == " + ep.Uri.AbsoluteUri);
Console.WriteLine("HTTP Method == " + ep.HttpMode);
Console.WriteLine("Timeout == " + ep.Timeout.ToString());
string query = "SELECT DISTINCT ?a\n"
+ "WHERE {\n"
+ " ?a <http://www.w3.org/2000/01/rdf-schema#label> ?b.\n"
+ "}\n"
+ "LIMIT 10\n";
ep.QueryWithResultSet(query,
(results, state) => {
output.Add(FormatResults(results, state));
},
"Query 1");
query = "SELECT DISTINCT ?v5 ?v8\n"
+ "WHERE {\n"
+ " {\n"
+ " SELECT DISTINCT ?v5\n"
+ " WHERE {\n"
+ " ?v6 ?v5 ?v7.\n"
+ " FILTER(regex(str(?v5), \"[/#]c[^/#]*$\", \"i\")).\n"
+ " }\n"
+ " OFFSET 0\n"
+ " LIMIT 20\n"
+ " }.\n"
+ " OPTIONAL {\n"
+ " ?v5 <http://www.w3.org/2000/01/rdf-schema#label> ?v8.\n"
+ " FILTER(lang(?v8) = \"en\").\n"
+ " }.\n"
+ "}\n"
+ "ORDER BY str(?v5)\n";
ep.QueryWithResultSet(query,
(results, state) => {
output.Add(FormatResults(results, state));
},
"Query 2");
Console.WriteLine("Queries sent.");
Console.WriteLine(DateTime.Now.ToLongTimeString());
Console.WriteLine();
string result = output.Take();
Console.WriteLine(result);
result = output.Take();
Console.WriteLine(result);
Console.ReadLine();
}
}
当我运行它时,我可以重现地得到如下输出:
13:13:23
Server == http://dbpedia.org/sparql
HTTP Method == GET
Timeout == 120
Queries sent.
13:13:25
13:13:25
Query 1
results.Count == 10
13:23:25
Query 2
VDS.RDF.Query.RdfQueryException: A HTTP error occurred while making an asynchron
ous query, see inner exception for details ---> System.Net.WebException: Der Rem
oteserver hat einen Fehler zurückgegeben: (504) Gatewaytimeout.
bei System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
bei VDS.RDF.Query.SparqlRemoteEndpoint.<>c__DisplayClass13.<QueryWithResultSe
t>b__11(IAsyncResult innerResult)
--- Ende der internen Ausnahmestapelüberwachung ---
results == null
显然,确切的时间会有所不同,但关键是在请求发送后大约 10 分钟 收到基于第二个查询的错误消息,与设置的 2 分钟相差甚远超时。
我是不是在这里错误地使用了 dotNetRDF,还是故意让我必须运行一个额外的计时器来自己测量超时并自行做出反应,除非同时收到任何响应?
【问题讨论】:
-
顺便说一句,
Timeout属性应该以毫秒而不是秒为单位设置,这在当前 API 文档中不够清楚,并且这已经由另一个用户报告并在中继中修复
标签: timeout sparql dbpedia dotnetrdf