并行检查文件中的打开端口ip

时间:2018-10-29 09:38:48

标签: c# task-parallel-library

我想检查一组ip中的开放端口。我不想顺序检查标题后面的IP。但我希望并行执行,以便用户确定线程数。 ip的数量分为多个线程:

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

检查打开的端口:

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

1 个答案:

答案 0 :(得分:1)

我每天都遇到这个问题,

将IO绑定操作放在Parallel.For中,没有为IO工作而设计或使用async模式(并相信我就是您想要的)是没有意义的。

我们为什么要使用async await模式?

因此,它设计为在等待IO完成端口或等待的工作负载时将线程交还给我们。

当您像这样在Parallel.For / Parallel.ForEach中运行IO工作时,Task Scheduler不会主动给您阻塞线程,它会使用各种启发式方法来计算出多少线程您应该有,并且它对此有一个模糊的看法。

那我们应该怎么用?

asyncawait模式

为什么?

因为,我们可以让IO成为IO,系统创建IO完成端口,.Net将线程返回到线程池,直到Completion端口回调并且方法继续。

因此,有很多选择。但是最重​​要的是,await是您正在使用的库的async可用方法。

从这里,您可以创建任务列表,并使用诸如等待的SemiphoreSlim之类的限制并发的WhenAll

或者您可以在TPL Dataflow中使用类似ActionBlock之类的工具,该工具旨在与受CPU和IO约束的工作负载一起使用。

现实世界的利益不可低估。您的Parallel.For方法只会运行少量线程并将其阻塞。一个异步版本,您将可以同时运行100秒

数据流示例

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