Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在多个线程之间拆分循环_C#_Multithreading - Fatal编程技术网

C# 在多个线程之间拆分循环

C# 在多个线程之间拆分循环,c#,multithreading,C#,Multithreading,我的代码从给定主机获取打开的端口。 这个过程非常耗时 代码: for(int port=0;port<11;port++) { string statusTCP = "Open"; using (TcpClient tcp = new TcpClient()) { try{ tcp.Connect("127.0.0.1",port); }catch { statusTCP="Close";} } Console.W

我的代码从给定主机获取打开的端口。 这个过程非常耗时

代码:

for(int port=0;port<11;port++)
{
    string statusTCP = "Open";
    using (TcpClient tcp = new TcpClient())
    {
         try{ tcp.Connect("127.0.0.1",port);
         }catch { statusTCP="Close";}
    }
    Console.WriteLine("Port " + port + " : " + statusTCP);
}

for(int-port=0;port如果您要问的是如何并行运行多个查找,请查看
parallel

Parallel.For(0, 11, new ParallelOptions { MaxDegreeOfParallelism = 5 }, (port) =>
{
    string statusTCP = "Open";
    using (TcpClient tcp = new TcpClient())
    {
        try
        {
            tcp.Connect("127.0.0.1", port);
        }
        catch { statusTCP = "Close"; }
    }
    Console.WriteLine("Port " + port + " : " + statusTCP);
});

请注意,在前几个方法参数中,我指定从0到10(因为11是互斥的),并与
ParallelOptions
类并行执行5次查找。

如果您要问的是如何并行运行多个查找,请查看
parallel

Parallel.For(0, 11, new ParallelOptions { MaxDegreeOfParallelism = 5 }, (port) =>
{
    string statusTCP = "Open";
    using (TcpClient tcp = new TcpClient())
    {
        try
        {
            tcp.Connect("127.0.0.1", port);
        }
        catch { statusTCP = "Close"; }
    }
    Console.WriteLine("Port " + port + " : " + statusTCP);
});

注意,在前几个方法参数中,我指定从0到10(因为11是独占的)并与
ParallelOptions
类并行执行5次查找。

连接到多个端口不需要多个线程。可以使用异步连接。Windows从NT开始通过完成端口使用异步IO

Parallel.For(0, 11, new ParallelOptions { MaxDegreeOfParallelism = 5 }, (port) =>
{
    string statusTCP = "Open";
    using (TcpClient tcp = new TcpClient())
    {
        try
        {
            tcp.Connect("127.0.0.1", port);
        }
        catch { statusTCP = "Close"; }
    }
    Console.WriteLine("Port " + port + " : " + statusTCP);
});
这意味着没有线程被阻塞,当IO请求完成时,操作系统会通知原始线程。事实上,阻塞是模拟的,以使同步编程更容易

您可以创建一个连接到单个端口的方法,并在完成时报告消息。但写入控制台会阻塞,因此我将使用该接口报告进度:

public async Task ConnectToPortAsync(string host,int port,IProgress<string> progress)
{
    using(var client=new TcpClient())
    {
        try
        {
            await client.ConnectAsync(host,port).ConfigureAwait(false);
            progress.Report($"Port: {port} Open");
            //Do some more work
        }
        catch 
        {
            progress.Report($"Port {port} Closed");
        }
    }
}

您可以同时调用多个端口,如下所示:

var host="127.0.0.1";
var progress=new Progress<string>(msg=>Console.WriteLine(msg););

var allTasks= ports.Select(port=>ConnectToPortAsync(host,port,progress));

await Task.WhenAll(allTasks);

连接到多个端口不需要多个线程。可以使用异步连接。从NT开始,Windows通过完成端口使用异步IO

这意味着没有线程被阻塞,当IO请求完成时,操作系统会通知原始线程。事实上,阻塞是模拟的,以使同步编程更容易

您可以创建一个连接到单个端口的方法,并在完成时报告消息。但写入控制台会阻塞,因此我将使用该接口报告进度:

public async Task ConnectToPortAsync(string host,int port,IProgress<string> progress)
{
    using(var client=new TcpClient())
    {
        try
        {
            await client.ConnectAsync(host,port).ConfigureAwait(false);
            progress.Report($"Port: {port} Open");
            //Do some more work
        }
        catch 
        {
            progress.Report($"Port {port} Closed");
        }
    }
}

您可以同时调用多个端口,如下所示:

var host="127.0.0.1";
var progress=new Progress<string>(msg=>Console.WriteLine(msg););

var allTasks= ports.Select(port=>ConnectToPortAsync(host,port,progress));

await Task.WhenAll(allTasks);


如果需要使用线程和异步,则根本不需要多线程。您可以使用异步方法异步连接IE,使用IO完成端口机制,而不阻塞线程。还应该考虑向套接字添加超时。默认情况下,应该是1秒。扫描本地主机时太长。为此,可以使用:
tcpClient.ConnectAsync().Wait(超时)
@Pimich Wait blocks。这将浪费通过使用
ConnectAsync
Parallel获得的一切。for应该在可能的情况下使用线程和异步您根本不需要多线程。您可以使用异步方法异步连接-即使用底层IO完成端口机制而不阻塞线程D.还应该考虑向套接字添加超时。默认情况下,它应该是1秒,这在扫描本地主机时太长了。要做到这一点,可以使用:<代码> TCPclie.CelpTasyCy.()。
@Pimich Wait blocks。这将浪费使用
ConnectAsync
@alix54 Parallel所获得的一切。For不会挂起程序。主线程是使用的5个线程之一。是否等待所有连接完成?是否尝试调试?@PanagiotisKanavos我在
BackGroundWorker
中使用了此方法,我认为使用main方法…@alix54当您有TPL和Parallel.For时,使用BGW有什么意义?如果您希望循环在后台运行,请使用Task.run围绕它。BGW已过时,因为它的所有功能都由TPL提供(包括进度报告)。@alix54-BackgroundWorker和Console.WriteLine()你们在一起没有什么意义。所以你问了一个不好的问题,但仍然得到了一个好的答案。请自己解决集成问题。@alix54不管怎样,你是否尝试暂停调试器并检查“并行堆栈”窗口?这将显示哪些线程正在运行或停止not@alix54并行。For不会挂起程序。主线程是5个线程之一已使用线程。是否等待所有连接完成?是否尝试调试?@PanagiotisKanavos我在
BackGroundWorker
中使用了此方法,我不认为使用了主方法…@alix54当您使用TPL和并行时,使用BGW有什么意义?对于?如果您希望循环在后台运行,请使用Task.run.BGW围绕它是过时的,因为它的所有功能都由TPL提供(包括进度报告)。@alix54-BackgroundWorker和Console.WriteLine()你们在一起没有什么意义。所以你问了一个不好的问题,但仍然得到了一个好的答案。自己解决集成问题。@alix54不管怎样,你是否尝试暂停调试器并检查并行堆栈窗口?这将显示哪些线程正在运行?谢谢你的回答,但是你的方法有两个错误
1。我进度:找不到类型或命名空间名称“T”。进度。报告(…):无法从字符串转换为T
@alix54 oops,忘记使用
IProgress
,因此应该注意,使用线程(同时做事情会浪费CPU)和使用任务有很大区别(可以在不使用CPU时间的事情上避免CPU时间)。因此,线程同时执行任务,而任务将在将来某处给出结果。Wait只处理延迟。不完全是。任务使用线程。使用原始线程需要创建线程,这非常昂贵。任务可能会开始执行得更快,因为它将使用线程池线程。如果使用
Threadpo,也会发生同样的情况olThread.QueueWorkItem
。一个线程池可以增长到数千个线程。此外,使用IO时,执行阻塞工作的不是线程。如果使用Win32 API,则可以使用回调到原始线程的函数来执行异步IOOnly任务。Run可以将CPU绑定的工作移动到后台线程。async和Wait不创建ad传统螺纹