Implementation #1 - using Parallel loop
var client = new HttpClient();
var processes = new List<Task<object>>();
Parallel.ForEach(urls, url =>
{
processes.Add(client.GetAsync(url).Result.Content.ReadAsAsync<object>());
});
Task.WhenAll(processes);
Implementation #2 - using async method + Result
var client = new HttpClient();
var processes = new List<Task<object>>();
urls.ForEach(url =>
{
processes.Add(GetChain(client, url));
});
Task.WhenAll(processes);
async Task<object> GetChain(HttpClient client, string url)
{
return await client.GetAsync(url).Result.Content.ReadAsAsync<object>();
}
Implementation #3 - using async method + await
var client = new HttpClient();
var processes = new List<Task<object>>();
urls.ForEach(url =>
{
processes.Add(GetChain(client, url));
});
Task.WhenAll(processes);
async Task<object> GetChain(HttpClient client, string url)
{
var chain = await client.GetAsync(url);
return await chain.Content.ReadAsAsync<object>();
}
I like implementation #1 with Parallel loop, but there is a possibility that Parallel will create a new thread on each iteration and will consume more resources.
Questions
PS There are two "await" calls because HttpClient requests data, then read it asynchronously.
Extra question - are these lines the same?
method1.Result.method2 // get result immediately
method1.ContinueWith(data => data.Result.method2) // call both methods first
consider the following example . it helps your to find answer on your question:
private static readonly List<Uri> Urls = new List<Uri>() {
new Uri(""),
new Uri("") };
....
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var result1 = Urls.Select(GetContent).ToArray();
stopwatch.Stop();
Console.WriteLine($@"Synchronous and NOT In Parallel:{stopwatch.ElapsedMilliseconds}");
stopwatch.Restart();
var result2 = Urls.AsParallel().Select(GetContent).ToArray();
stopwatch.Stop();
Console.WriteLine($@"Synchronous and In Parallel:{stopwatch.ElapsedMilliseconds}");
stopwatch.Restart();
var task1 = DoAsyncNotParallel();
task1.Wait();
stopwatch.Stop();
Console.WriteLine($@"Asynchronous and NOT In Parallel:{stopwatch.ElapsedMilliseconds}");
stopwatch.Restart();
var task2 = DoAsyncInParallel();
task2.Wait();
stopwatch.Stop();
Console.WriteLine($@"Asynchronous and In Parallel:{stopwatch.ElapsedMilliseconds}");
static async Task<string[]> DoAsyncNotParallel()
{
List<string> content = new List<string>();
foreach (var uri in Urls)
{
content.Add(await GetContentAsync(uri));
}
return content.ToArray();
}
static async Task<string[]> DoAsyncInParallel()
{
var tasks = Urls.Select(uri => GetContentAsync(uri));
var content = await Task.WhenAll(tasks);
return content;
}
private static async Task<string> GetContentAsync(Uri uri)
{
HttpClient httpClient = new HttpClient();
var response = await httpClient.GetAsync(uri);
var content = await response.Content.ReadAsStringAsync();
return content;
}
private static string GetContent(Uri uri)
{
HttpClient httpClient = new HttpClient();
var response = httpClient.GetAsync(uri).Result;
var content = response.Content.ReadAsStringAsync().Result;
return content;
}
i recommend you to look through the following links which can be useful for you :
about last part of question:
method1.Result.method2();
calling thread is blocked until method1 is completed, then method2 is being called
method1.ContinueWith(data => data.Result.method2());
calling thread is not blocked, method1 is being executed asynchronously . once method1 is completed, then new Task is running like Task.Run(()=>{ method1.Result.method2()}). in this case method1.Result doesn't block calling thread because method1 alread completed, isCompleted=true
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.