Reputation: 6839
In my ASP.NET MVC4 application I have a controller action in which I go out to several external websites and collect information which I show on my page in an aggregated way. Obviously, I want to do this in parallel, so I have written my code similar to this:
var client1 = new HttpClient().GetAsync("http://google.com");
var client2 = new HttpClient().GetAsync("http://stackoverflow.com");
var client3 = new HttpClient().GetAsync("http://twitter.com");
var result1 = client1.Result;
var result2 = client2.Result;
var result3 = client3.Result;
How can I find out how long each request took to finish, so that I can display that information on my page?
Upvotes: 15
Views: 21656
Reputation: 8616
I would probably try something like the following:
EDIT: Updated to make the HttpClient
a static instance.
static HttpClient client = new HttpClient();
private async void _HttpServerDemo()
{
var info1 = _GetHttpWithTimingInfo("http://google.com");
var info2 = _GetHttpWithTimingInfo("http://stackoverflow.com");
var info3 = _GetHttpWithTimingInfo("http://twitter.com");
await Task.WhenAll(info1, info2, info3);
Console.WriteLine("Request1 took {0}", info1.Result);
Console.WriteLine("Request2 took {0}", info2.Result);
Console.WriteLine("Request3 took {0}", info3.Result);
}
private async Task<Tuple<HttpResponseMessage, TimeSpan>> _GetHttpWithTimingInfo(string url)
{
var stopWatch = Stopwatch.StartNew();
var result = await client.GetAsync(url);
return new Tuple<HttpResponseMessage, TimeSpan>(result, stopWatch.Elapsed);
}
Upvotes: 19
Reputation: 4151
There is now one option in .NET Core which might give you better results, at least in my case the elapsed time is lower around 10-40% than using the method suggested by @ollifant. I would stay with his suggestion but moved the Stopwatch to the handler.
You can use DelegatingHandler, example .NET Core Docs.
You can still use Stopwatch as suggested above but rather in the handler itself. I add elapsed time to the Header which I retreive then in e.g your _GetHttpWithTimingInfo and process further. Most likely you could DI some services and save the duration to the database from the handler itself, depends on your project..
Maybe, this solution might also resolve problem mentioned by @Dmytro Bogatov.
Also, this method is used directly in .NET Core HTTP logging check SendAsync. Note they are using internal ValueStopwatch instead Stopwatch.
These logs are showing using Stopwatch in the Handler vs directly in the method:
08-11-2020 18:05:52.024 [INF] Handler: 992, _GetHttpWithTimingInfo 995
08-11-2020 18:05:52.153 [INF] Handler: 663, _GetHttpWithTimingInfo 1249
08-11-2020 18:05:52.208 [INF] Handler: 999, _GetHttpWithTimingInfo 1220
08-11-2020 18:05:52.219 [INF] Handler: 1002, _GetHttpWithTimingInfo 1241
08-11-2020 18:05:52.219 [INF] Handler: 989, _GetHttpWithTimingInfo 1217
08-11-2020 18:05:52.255 [INF] Handler: 609, _GetHttpWithTimingInfo 1302
08-11-2020 18:05:52.260 [INF] Handler: 959, _GetHttpWithTimingInfo 1267
08-11-2020 18:05:52.287 [INF] Handler: 1063, _GetHttpWithTimingInfo 1303
08-11-2020 18:05:52.292 [INF] Handler: 515, _GetHttpWithTimingInfo 1381
08-11-2020 18:05:52.296 [INF] Handler: 992, _GetHttpWithTimingInfo 1286
08-11-2020 18:05:52.321 [INF] Handler: 953, _GetHttpWithTimingInfo 1323
08-11-2020 18:05:52.324 [INF] Handler: 973, _GetHttpWithTimingInfo 1304
08-11-2020 18:05:52.326 [INF] Handler: 985, _GetHttpWithTimingInfo 1302
Upvotes: 3