什么';s是使方法异步运行的最佳方法
本文关键字:方法 异步 运行 最佳 什么 | 更新日期: 2023-09-27 18:20:07
嗨,我是异步编程的新手。如何运行我的方法checkAvaible来运行async?如果可能的话,我想一次下载2500页,不要等着完成一次下载再开始另一次。我该怎么做?
private static void searchForLinks()
{
string url = "http://www.xxxx.pl/xxxx/?action=xxxx&id=";
for (int i = 0; i < 2500; i++)
{
string tmp = url;
tmp += Convert.ToString(i);
checkAvaible(tmp); // this method run async, do not wait while one page is downloading
}
Console.WriteLine(listOfUrls.Count());
Console.ReadLine();
}
private static async void checkAvaible(string url)
{
using (WebClient client = new WebClient())
{
string htmlCode = client.DownloadString(url);
if (htmlCode.IndexOf("Brak takiego obiektu w naszej bazie!") == -1)
listOfUrls.Add(url);
}
}
- 您不希望同时下载2500个页面,因为这对您的客户端和服务器都是一个问题。相反,我添加了并发下载限制(默认为10)。网页将被下载,每次10页。(或者,如果你运行的是超级计算机,你可以将其更改为2500:)
- Generic Lists(在您的情况下,我认为它是字符串列表)默认情况下不是线程安全的,因此您应该同步对Add方法的访问。我还补充了这一点
以下是更新的源代码,可以通过可配置的并发调用异步下载页面
private static List<string> listOfUrls = new List<string>();
private static void searchForLinks()
{
string url = "http://www.xxxx.pl/xxxx/?action=xxxx&id=";
int numberOfConcurrentDownloads = 10;
for (int i = 0; i < 2500; i += numberOfConcurrentDownloads)
{
List<Task> allDownloads = new List<Task>();
for (int j = i; j < i + numberOfConcurrentDownloads; j++)
{
string tmp = url;
tmp += Convert.ToString(i);
allDownloads.Add(checkAvaible(tmp));
}
Task.WaitAll(allDownloads.ToArray());
}
Console.WriteLine(listOfUrls.Count());
Console.ReadLine();
}
private static async Task checkAvaible(string url)
{
using (WebClient client = new WebClient())
{
string htmlCode = await client.DownloadStringTaskAsync(new Uri(url));
if (htmlCode.IndexOf("Brak takiego obiektu w naszej bazie!") == -1)
{
lock (listOfUrls)
{
listOfUrls.Add(url);
}
}
}
}
最好从内部和外部将代码转换为async
。遵循最佳实践,例如避免使用async void
,使用Async
后缀,并返回结果而不是修改共享变量:
private static async Task<string> checkAvaibleAsync(string url)
{
using (var client = new HttpClient())
{
string htmlCode = await client.GetStringAsync(url);
if (htmlCode.IndexOf("Brak takiego obiektu w naszej bazie!") == -1)
return url;
else
return null;
}
}
然后,您可以使用Task.WhenAll
:同时启动任意数量的
private static async Task<string[]> searchForLinksAsync()
{
string url = "http://www.xxxx.pl/xxxx/?action=xxxx&id=";
var tasks = Enumerable.Range(0, 2500).Select(i => checkAvailableAsync(url + i));
var results = await Task.WhenAll(tasks);
var listOfUrls = results.Where(x => x != null).ToArray();
Console.WriteLine(listOfUrls.Length);
Console.ReadLine();
}