私はこの方法を持っています:
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 > Break All (Pause) を実行し、次の行で停止しました:
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: