2013-09-30 31 views
3

我有這樣的方法:爲什麼我收到異常:阻塞操作被WSACancelBlockingCall調用中斷?

public DateTime GetNetworkTime() 
     { 
      DateTime networkDateTime = DateTime.Now; 
      try 
      { 
      IPAddress[] addresses = null; 
      //default Windows time server 
      const string ntpServer = "time.windows.com"; 
      const string ntpServer1 = "time.nist.gov"; 
      const string ntpServer2 = "time-nw.nist.gov"; 
      const string ntpServer3 = "time-a.nist.gov"; 
      const string ntpServer4 = "time-b.nist.gov"; 
      List<string> ntpServersList = new List<string>(); 
      ntpServersList.Add(ntpServer); 
      ntpServersList.Add(ntpServer1); 
      ntpServersList.Add(ntpServer2); 
      ntpServersList.Add(ntpServer3); 
      ntpServersList.Add(ntpServer4); 

      // NTP message size - 16 bytes of the digest (RFC 2030) 
      var ntpData = new byte[48]; 

      //Setting the Leap Indicator, Version Number and Mode values 
      ntpData[0] = 0x1B; //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode) 

      for (int i = 0; i < ntpServersList.Count; i++) 
      { 
       addresses = Dns.GetHostEntry(ntpServersList[i]).AddressList; 
       if (addresses.Length > 0) 
       { 
        break; 
       } 
      } 


      //The UDP port number assigned to NTP is 123 
      var ipEndPoint = new IPEndPoint(addresses[0], 123); 
      //NTP uses UDP 
      var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 

      socket.Connect(ipEndPoint); 
      socket.Send(ntpData); 
       Thread th = new Thread(()=> 
       { 
        socket.Receive(ntpData); 
        flag.Set(); 
       }); 
       th.IsBackground = true; 
       th.Start(); 

       //Block the current thread for 5 seconds 
       flag.WaitOne(5000, false); 
      socket.Close(); 

      //Offset to get to the "Transmit Timestamp" field (time at which the reply 
      //departed the server for the client, in 64-bit timestamp format." 
      const byte serverReplyTime = 40; 

      //Get the seconds part 
      ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime); 

      //Get the seconds fraction 
      ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4); 

      //Convert From big-endian to little-endian 
      intPart = SwapEndianness(intPart); 
      fractPart = SwapEndianness(fractPart); 

      var milliseconds = (intPart * 1000) + ((fractPart * 1000)/0x100000000L); 

      //**UTC** time 
      networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds); 
      } 
      catch(Exception err) 
      { 
       MessageBox.Show("error" + err.ToString()); 
      } 
      return networkDateTime.ToLocalTime(); 
     } 

在Form1的頂部我沒有:

AutoResetEvent flag; 

在構造:

flag = new AutoResetEvent(false); 

然後在GetNetworkTime上述方法()中的我改變的部分是:

Thread th = new Thread(()=> 
       { 
        socket.Receive(ntpData); 
        flag.Set(); 
       }); 
       th.IsBackground = true; 
       th.Start(); 

       //Block the current thread for 5 seconds 
       flag.WaitOne(5000, false); 

使用標誌和線程程序之前是杭/凍結,我也DEBUG>打破一切(暫停) 它停就行了:

socket.Receive(ntpData); 

,所以我說這個標誌和線程的代碼。 現在運行我的程序我得到就行此異常時:

socket.Receive(ntpData); 

SocketException 阻塞操作是通過調用中斷WSACancelBlockingCall

System.Net.Sockets.SocketException was unhandled 
    HResult=-2147467259 
    Message=A blocking operation was interrupted by a call to WSACancelBlockingCall 
    Source=System 
    ErrorCode=10004 
    NativeErrorCode=10004 
    StackTrace: 
     at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) 
     at System.Net.Sockets.Socket.Receive(Byte[] buffer) 
     at TestDateTime.Form1.<>c__DisplayClass1.<GetNetworkTime>b__0() in d:\C-Sharp\TestDateTime\TestDateTime\TestDateTime\Form1.cs:line 125 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException: 
+2

當您嘗試「接收」時,您正在強制關閉套接字。結果令人驚訝嗎? – Jon

回答

4

後等待您關閉套接字。這取消了同步讀取調用,這是一件好事。這也意味着你應該處理這個異常。一定要匹配ErrorCode=10004屬性。你不想吞下其他錯誤。

相關問題