我想尽快命中过多(100k+)的JSON文件,序列化它们,并存储请求的HTTP响应状态代码(无论成功还是失败)。 (我正在使用System.Runtime.Serialization.Json
和DataContract
)。 我打算对状态代码和序列化对象进行进一步的工作,但作为测试平台,我有以下代码片段:
List<int> ids = new List<int>();
for (int i = MIN; i < MAX; i++)
ids.Add(i);
var tasks = ids.Select(id =>
{
var request = WebRequest.Create(GetURL(id));
return Task
.Factory
.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, id)
.ContinueWith(t =>
{
HttpStatusCode code = HttpStatusCode.OK;
Item item = null;
try
{
using (var stream = t.Result.GetResponseStream())
{
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(Item));
item = ((Item)jsonSerializer.ReadObject(stream));
}
}
catch (AggregateException ex)
{
if (ex.InnerException is WebException)
code = ((HttpWebResponse)((WebException)ex.InnerException).Response).StatusCode;
}
});
}).ToArray();
Task.WaitAll(tasks);
使用这种方法,我能够比以前使用的同步方法更快地处理文件。
不过,我知道当状态代码为4xx
或5xx
时,GetResponseStream()
会抛出WebException
。 因此,要捕获这些状态代码,我需要捕获此异常。 但是,在此 TPL 的上下文中,它嵌套在AggregateException
上的InnerException
中。 这使得这句话真的很混乱:
code = ((HttpWebResponse)((WebException)ex.InnerException).Response).StatusCode;
虽然,这有效...我想知道在这种情况下是否有更好/更清晰的方法来捕获此类异常?
查看 MSDN 文章:异常处理(任务并行库)
例如,您可能希望按如下方式重写代码:
try
{
using (var stream = t.Result.GetResponseStream())
{
DataContractJsonSerializer jsonSerializer = new
DataContractJsonSerializer(typeof(Item));
item = ((Item)jsonSerializer.ReadObject(stream));
}
}
catch (AggregateException ex)
{
foreach (var e in ex.InnerExceptions)
{
bool isHandled = false;
if (e is WebException)
{
WebException webException = (WebException)e;
HttpWebResponse response = webException.Response as HttpWebResponse;
if (response != null)
{
code = response.StatusCode;
isHandled = true;
}
}
if (!isHandled)
throw;
}
}
试试这个大小。 GetBaseException 返回导致问题的异常。
try
{
}
catch (System.AggregateException aex)
{
var baseEx = aex.GetBaseException() as WebException;
if (baseEx != null)
{
var httpWebResp = baseEx.Response as HttpWebResponse;
if (httpWebResp != null)
{
var code = httpWebResp.StatusCode;
// Handle it...
}
}
throw;
}