Reputation: 3161
I want to hit a plethora (100k+) of JSON files as rapidly as possible, serialize them, and store the HTTP response status code of the request (whether it succeeded or failed). (I am using System.Runtime.Serialization.Json
and a DataContract
). I intend to do further work with the status code and serialized object, but as a test bed I have this snippet of code:
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);
Using this approach I was able to process files much more quickly than the synchronous approach I was doing before.
Though, I know that the GetResponseStream()
throws the WebException
when the status code is 4xx
or 5xx
. So to capture those status codes I need to catch this exception. However, in the context of this TPL it is nested in an InnerException
on an AggregateException
. This makes this line really confusing:
code = ((HttpWebResponse)((WebException)ex.InnerException).Response).StatusCode;
Though, this works... I was wondering if there is a better/clearer way to capture such an exception in this context?
Upvotes: 0
Views: 2532
Reputation: 3560
Try this on for size. GetBaseException returns the exception that caused the problem.
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;
}
Upvotes: 1
Reputation: 4917
Take a look at MSDN article: Exception Handling (Task Parallel Library)
For example, you might want to rewrite your code as follows:
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;
}
}
Upvotes: 2