【发布时间】:2017-05-05 13:44:05
【问题描述】:
下面我有一个应用程序,我尝试使用 C# 套接字以最快的方式发送尽可能多的数据。数据开始 10 秒后,我停止数据发送并等待控制台键,同时向控制台写入发送了多少请求。
将线程数设置为 1 时,我收到了更高的请求。这是日志
Attempt 1 => 86873
Attempt 2 => 107324
Attempt 3 => 97426
Attempt 4 => 94720
Attempt 5 => 97927
Attempt 6 => 94327
Attempt 7 => 94791
如您所见,它的峰值大约在 80,000 到 110,000 之间。当将其设置为高于 1(我尝试了 1 和 2)时,它甚至没有达到 80,000,它在 10 秒内达到大约 70-75000。我的想法是更多的线程=发送更多的数据,因为它在幕后做了更多的工作?谁能给我一些这方面的信息?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace RDOS
{
public class ThreadHandler
{
private int count = 0;
private int threadCount = 3;
private List<Thread> _threads = new List<Thread>();
private string _ip;
private int _port;
public int RequestsSent;
public int RequestsFailed;
public DateTime Started;
public ThreadHandler()
{
Console.Write("IP: ");
_ip = Console.ReadLine();
Console.Write("Port: ");
_port = int.Parse(Console.ReadLine());
Console.WriteLine("sending data to " + _ip + " on port " + _port);
Thread backgroundThread = new Thread(new ThreadStart(OnBackgroundThread));
backgroundThread.Start();
for (int i = 0; i < threadCount; i++)
{
_threads.Add(new Thread(new ThreadStart(OnThread)));
}
foreach (Thread thread in _threads)
{
thread.Start();
}
}
public void OnBackgroundThread()
{
Started = DateTime.Now;
while (true)
{
System.Threading.Thread.Sleep(10000);
TimeSpan span = DateTime.Now - Started;
Console.WriteLine("Sent " + RequestsSent + " requests (running for " + span.TotalSeconds + ")");
Console.ReadKey();
}
}
public void OnThread()
{
IPEndPoint RHost = new IPEndPoint(IPAddress.Parse(_ip), _port);
using (Socket socket = new Socket(RHost.AddressFamily, SocketType.Dgram, ProtocolType.Udp))
{
socket.Blocking = true;
while (true)
{
RequestsSent++;
byte[] buf = System.Text.Encoding.ASCII.GetBytes("fwkdkskdsksk");
socket.SendTo(buf, SocketFlags.None, RHost);
}
}
}
}
}
【问题讨论】:
-
我对套接字了解不多,但我认为这可能是个问题
socket.Blocking = true; -
老兄,你的测量代码有一个很大的缺陷,
RequestsSent必须至少标记为volatile,否则.net会在调用之间缓存值,所以多个线程会看到以前的值和因此计数器没有按您预期的那样工作。即使使用 volatile 也会丢失一些值,最好在更新之前锁定值。 -
写入
Console也会导致线程同步。 See here -
@Amy 我在线程方法中看不到任何
Console写入 -
namespace RDOS...嗯。
标签: c# multithreading