你可以跳过这部分:
我正在创建一个客户端需要在同一网络上找到服务器的应用程序。
服务器:
public static void StartListening(Int32 端口) {
TcpListener server = new TcpListener(IP.GetCurrentIP(), port);
server.Start();
Thread t = new Thread(new ThreadStart(() =>
{
while (true)
{
// wait for connection
TcpClient client = server.AcceptTcpClient();
if (stopListening)
{
break;
}
}
}));
t.IsBackground = true;
t.Start();
假设服务器正在监听端口 12345
然后客户端:
- 获取客户端的当前 ip 地址假设它是 192.168.5.88
创建所有可能的 IP 地址列表。服务器 ip 地址可能与客户端的 ip 地址有关,如果它们在同一本地网络上,因此我将列表构造为:
192.168.5.0 192.168.5.1 192.168.5.2 192.168.5.3 .....etc ..... 192.168.0.88 192.168.1.88 192.168.2.88 192.168.3.88 ...etc 192.0.5.88 192.1.5.88 192.2.5.88 192.3.5.88 192.4.5.88 ..... etc 0.168.5.88 1.168.5.88 2.168.5.88 3.168.5.88 4.168.5.88 .... etc
然后我尝试连接每个可能的 ip 和端口 12345。如果一个连接成功,则意味着我找到了服务器的地址。
现在我的问题是:
现在我用两种方式做到了这一点。我只知道有关线程的基础知识,我不知道这是否危险,但它工作得非常快。
// first way
foreach (var ip in ListOfIps)
{
new Thread(new ThreadStart(() =>
{
TryConnect(ip);
})).Start();
}
我认为第二种方式更安全,但需要更多时间:
// second way
foreach (var ip in ListOfIps)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(TryConnect), ip);
}
我必须调用 TryConnect 方法大约 1000 次,每次大约需要 2 秒(我将连接超时设置为 2 秒)。调用它 1000 次的最有效和最安全的方法是什么?
编辑2
以下是使用不同技术的结果:
1) Using threadpool
..
..
var now = DateTime.Now;
foreach (var item in allIps)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), item);
}
ThreadPool.QueueUserWorkItem(new WaitCallback(PrintTimeDifference), now);
}
static void PrintTimeDifference(object startTime)
{
Console.WriteLine("------------------Done!----------------------");
var s = (DateTime)startTime;
Console.WriteLine((DateTime.Now-s).Seconds);
}
完成需要 37 秒
2) Using threads:
..
..
var now = DateTime.Now;
foreach (var item in allIps)
{
new Thread(new ThreadStart(() =>
{
DoWork(item);
})).Start();
}
ThreadPool.QueueUserWorkItem(new WaitCallback(PrintTimeDifference), now);
完成需要 12 秒
3) Using tasks:
..
..
var now = DateTime.Now;
foreach (var item in allIps)
{
var t = Task.Factory.StartNew(() =>
DoWork(item)
);
}
ThreadPool.QueueUserWorkItem(new WaitCallback(PrintTimeDifference), now);
}
static void PrintTimeDifference(object startTime)
{
Console.WriteLine("------------------Done!----------------------");
var s = (DateTime)startTime;
Console.WriteLine((DateTime.Now-s).Seconds);
}
花了 8 秒!!
最佳答案
在这种情况下,我更喜欢 ThreadPool-Threads 的解决方案,因为创建 1000 个线程是一项繁重的操作(当您考虑每个线程获得的内存时)。
但是自 .NET 4 以来,还有另一个解决方案,类 Task
。
任务是可以并行执行的工作负载。您可以像这样定义和运行它们:
var t = Task.Factory.StartNew(() => DoAction());
您不必关心使用的线程数,因为运行时环境会处理它。因此,如果您有可能将您的工作负载拆分成可以并行执行的更小的包,我会使用 Tasks 来完成这项工作。
关于c# - 执行多个线程的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9953856/