0

I want to check the open port in a group of ip . I do not want to check an ip behind a title sequentially. But I want it in parallel so that the user determines the number of threads. The number of ip is divided into threads :

    private async void button3_Click(object sender, EventArgs e)
    {
        await Task.Run(() => 
        {
            var lines = File.ReadAllLines("ip.txt");
            int cc = (lines.Length) / (int.Parse(thread.Text));
            if (lines.Length % int.Parse(thread.Text) == 0)
            {
                for (int s = 0; s < lines.Length; s = s + cc)
                {
                    Parallel.For(0, 1, a =>
                    {
                        checkopen(s, (s + cc));
                    });
                }
            }
            else
            {
                MessageBox.Show("enter true thread num");
            }
        });
    }

this to check open port :

    void checkopen(int first,int last)
    {
        int port = Convert.ToInt32(portnum.Text);
        var lines = File.ReadAllLines("ip.txt");
        for (int i = first; i < last; ++i)
        {
            var line = lines[i];
            using (TcpClient tcpClient = new TcpClient())
            {
                    try
                    {
                        tcpClient.Connect(line, port);
                        this.Invoke(new Action(() =>
                        {
                            listBox1.Items.Add(line); // open port
                        }));
                    }
                    catch (Exception)
                    {
                        this.Invoke(new Action(() =>
                        {
                            listBox2.Items.Add(line); //close port
                        }));
                    }
            }
        }
    }
  • I think this is a duplicate to https://stackoverflow.com/questions/9290498/how-can-i-limit-parallel-foreach – Daniel W. Oct 29 '18 at 09:42
  • Possible duplicate of [Limit number of Threads in Task Parallel Library](https://stackoverflow.com/questions/23105748/limit-number-of-threads-in-task-parallel-library) – Daniel W. Oct 29 '18 at 09:43
  • Thank you brother but did not understand my intention .. I do not want to limit the number of parallel, but I want to use the maximum number of parallelism – Mohammad Shaheen Oct 29 '18 at 10:43

1 Answers1

1

I see this problem every day,

There is no point putting IO bound operations in Parallel.For, its not designed for IO work, or the async pattern (and trust me thats what you want).

Why do we want the async await pattern?

Because, it designed to give the threads back when its awaiting an IO completion port or awaitable workload.

When you run IO work in Parallel.For/Parallel.ForEach like this, the Task Scheduler just wont aggressive give you threads to block, it uses all sort of heuristics to work out how many threads you should have, and it takes a dim view of it.

So what should we use?

The async and await pattern

Why?

Because, we can let IO be IO, the system creates and IO completion port, .Net gives the thread back to the threadpool until the Completion port calls backs and the method continues.

So, there are many options for this. But first and foremost await the awaitable async methods of the libraries you are using.

From here you can either create a lists of tasks and use something like an awaitable SemiphoreSlim to limit concurrency and a WhenAll.

Or you could use something like an ActionBlock out of TPL Dataflow, which is designed to work with both CPU and IO bound workloads.

The real world benefits cant be understated. Your Parallel.For approach will just run a handful of thread and block them. An async version you'll be able to run 100s simultaneously

Dataflow example

You can get the Nuget here

public async Task DoWorkLoads(List<WorkLoad> workloads)
{
   var options = new ExecutionDataflowBlockOptions
                     {
                        // add pepper and salt to taste
                        MaxDegreeOfParallelism = 100,
                        EnsureOrdered = false
                     };

   // create an action block
   var block = new ActionBlock<WorkLoad>(MyMethodAsync, options);

   // Queue them up
   foreach (var workLoad in workloads)
      block.Post(workLoad );

   // wait for them to finish
   block.Complete();
   await block.Completion;

}

...

// Notice we are using the async / await pattern
public async Task MyMethodAsync(WorkLoad workLoad)
{

    try
    {
        Console.WriteLine("Doing some IO work async);
        await DoIoWorkAsync;
    }
    catch (Exception)
    {
        // probably best to add some error checking some how
    }
}
TheGeneral
  • 75,627
  • 8
  • 79
  • 119
  • Thank you brother .. but I want to check the open port in the group ip. At the least time . so I want to use parallelism. Is there another way? – Mohammad Shaheen Oct 29 '18 at 11:00
  • @MohammadShaheen updated with a an async aware TPL dataflow example, all you have to do is add your async code. However be aware, you will need to use a thread safe collection if you want to store any results – TheGeneral Oct 29 '18 at 11:06