2017-05-05 106 views
-1

下面我有一个应用程序,我试图发送尽可能多的数据以尽可能快的方式使用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)时,它甚至没有达到8万,在10秒内达到70-75万。我的想法是更多的线程=更多的数据发送,因为它在幕后做更多的工作?任何人都可以给我一些这方面的信息吗?

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

我不太了解套接字,但我认为这可能是一个问题'socket.Blocking = true;' – TheLethalCoder

+4

老兄,你的测量代码有一个很大的缺陷,'RequestsSent'必须至少标记为volatile ',否则.net会缓存调用之间的值,因此多个线程会看到以前的值,因此计数器不能按照您的预期工作。即使使用volatile,它也会丢失一些值,在更新值之前更好地锁定值。 – Gusman

+0

写入'Console'还会导致线程同步。 [见这里](https://stackoverflow.com/questions/29960436/why-is-my-multi-threading-slower-than-my-single-threading) – Amy

回答

6

此外the thread safety error which is causing you to get lower than actual numbers,虽然你可能有多个线程,但你仍然只有一个网络适配器,也有可能是你的瓶颈。

在I/O界限问题下投掷更多的CPU能量不会让你的I/O速度更快,实际上大多数情况下,由于锁定OS导致的开销会导致I/O速度降低必须做到序列化访问I/O设备。获得更快I/O的唯一方法是获得更快的硬件。

+0

然后我只需要运行1个线程会更好吗?另外,我将如何解决线程安全错误,锁定整个线程方法? –

+1

用'Interlocked.Increment(ref RequestsSent)'替换'RequestsSent ++;';'修复线程安全错误。至于穿线,我会从1开始,然后慢慢上升,测量比率并查看最佳位置。 –