-1

I did this:

WebClient client = new WebClient();
string[] dns = client.DownloadString("https://public-dns.info/nameservers.txt")
    .Split('\n');
List<string> parsedDns = new List<string>();
foreach (string dnsStr in dns)
{
    Ping ping = new Ping();
    if (dnsStr.Contains(":"))
    {

    }
    else if (ping.SendPingAsync(dnsStr, 150).Result.RoundtripTime <= 150)
    {
        parsedDns.Add(dnsStr);
    }
}

foreach (var dns_ in parsedDns.ToArray())
{
   Console.WriteLine(dns_);
}
Console.ReadKey();

That what it does is collect the DNS of a page, put them in a string[] and then ping them one by one and those with less than 150ms of response are saved and printed on the console. I tried to do it with multithreads but it kept giving me errors and I would like to know how it would be to do this with for example 500 threads without any bugs in order to increase the speed of this process.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
vitem
  • 15
  • 6
  • With 500 threads you're probably gonna crush your computer's resources, to be honest. – Etienne de Martel Feb 03 '22 at 19:13
  • 7
    `but it kept giving me errors` Always post the error. – LarsTech Feb 03 '22 at 19:14
  • 3
    use TPL, Parallel.ForEach etc https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-parallel-library-tpl – pm100 Feb 03 '22 at 19:14
  • @EtiennedeMartel I've already tried it with 500 threads and it lags the computer a bit but at least it doesn't crash me. Something that I have not mentioned is that I would also like you to be able to change the threads that you want to be created – vitem Feb 03 '22 at 19:16
  • 1
    Don't create that many threads, use the thread pool. – Etienne de Martel Feb 03 '22 at 19:19
  • 3
    You don't want to create threads, create tasks. Creating threads allows you to create more threads than cores on your system which is a recipe for disaster. Always do the most high-level thing you can do, which for .NET and multithreaded operations is tasks. – Lasse V. Karlsen Feb 03 '22 at 19:20
  • 2
    While TPL definitely is what you should learn further, `ping.SendPingAsync(dnsStr, 150).Result` is also a common mistake made by new users of such async API. Proper usage of TPL and `async/await` is essential to write good multithreading applications. – Lex Li Feb 03 '22 at 19:47

1 Answers1

0

You could use the Parallel.ForEachAsync API, that was introduced in .NET 6.

var parsedDns = new ConcurrentQueue<string>();
var options = new ParallelOptions() { MaxDegreeOfParallelism = 10 };

Parallel.ForEachAsync(dns, options, async (dnsStr, ct) =>
{
    Ping ping = new();
    PingReply reply = await ping.SendPingAsync(dnsStr, 150);
    if (reply.RoundtripTime <= 150)
    {
        parsedDns.Enqueue(dnsStr);
    }
}).Wait();

The Parallel.ForEachAsync method returns a Task that you can either await, or simply Wait as in the above example.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
  • Im using .net framework 4.8 – vitem Feb 03 '22 at 21:02
  • Any reason why you're stuck on an ancient framework? – Etienne de Martel Feb 03 '22 at 21:13
  • @vitem you can find an alternative to `Parallel.ForEachAsync` [here](https://stackoverflow.com/questions/11564506/nesting-await-in-parallel-foreach/65251949#65251949), that requires to install the [TPL Dataflow](https://www.nuget.org/packages/System.Threading.Tasks.Dataflow/) package in .NET Framework 4.8. There are many custom implementations of this method, scattered in various questions in this site. – Theodor Zoulias Feb 04 '22 at 10:33