简体   繁体   English

使方法异步运行的最佳方法是什么?

[英]What's the best way to make method run async?

Hi i'm new in async programming. 嗨,我是异步编程的新手。 How can I run my method checkAvaible to run async? 如何运行我的方法checkAvaable来异步运行? I would like to download 2500 pages at once if it's possible, dont wait to complete one download and start another. 如果可能的话,我想一次下载2500页,请不要等待完成一次下载然后再开始下载。 How can I make it? 我该怎么做?

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);
        }
    }
  1. You would not want to download 2500 pages at the same time since this will be a problem for both your client and the server. 您不希望同时下载2500页,因为这对您的客户端和服务器都是一个问题。 Instead, I have added a concurrent download limitation (of 10 by default). 相反,我添加了一个并发下载限制(默认为10个)。 The web pages will be downloaded 10 page at a time. 网页将一次下载10页。 (Or you can change it to 2500 if you are running a super computer :)) (或者,如果您正在运行超级计算机,则可以将其更改为2500 :)
  2. Generic Lists (I think it is a List of strings in your case) is not thread safe by default therefore you should synchronize access to the Add method. 通用列表(我认为这是您的情况下的字符串列表)默认情况下不是线程安全的,因此您应该同步对Add方法的访问。 I have also added that. 我还补充了这一点。

Here is the updated source code to download pages asynhcronously with a configurable amount of concurrent calls 这是更新的源代码,可通过可配置数量的并发调用异步下载页面

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);
            }
        }
    }
}

It's best to convert code to async by working from the inside and proceeding out. 最好通过从内部进行工作然后继续进行,将代码转换为async代码。 Follow best practices along the way, such as avoiding async void , using the Async suffix, and returning results instead of modifying shared variables: 按照沿途的最佳做法,如避免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;
  }
}

You can then start off any number of these concurrently using Task.WhenAll : 然后,您可以使用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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM