我想检查一组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
}));
}
}
}
}
答案 0 :(得分:1)
我每天都遇到这个问题,
将IO绑定操作放在Parallel.For
中,没有为IO工作而设计或使用async
模式(并相信我就是您想要的)是没有意义的。
我们为什么要使用async
await
模式?
因此,它设计为在等待IO完成端口或等待的工作负载时将线程交还给我们。
当您像这样在Parallel.For
/ Parallel.ForEach
中运行IO工作时,Task Scheduler
不会主动给您阻塞线程,它会使用各种启发式方法来计算出多少线程您应该有,并且它对此有一个模糊的看法。
那我们应该怎么用?
async
和await
模式
为什么?
因为,我们可以让IO成为IO,系统创建IO完成端口,.Net将线程返回到线程池,直到Completion端口回调并且方法继续。
因此,有很多选择。但是最重要的是,await
是您正在使用的库的async
可用方法。
从这里,您可以创建任务列表,并使用诸如等待的SemiphoreSlim
之类的限制并发的WhenAll
。
或者您可以在TPL Dataflow中使用类似ActionBlock
之类的工具,该工具旨在与受CPU和IO约束的工作负载一起使用。
现实世界的利益不可低估。您的Parallel.For
方法只会运行少量线程并将其阻塞。一个异步版本,您将可以同时运行100秒
数据流示例
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
}
}