2013-09-29 24 views
1

至少有一次或兩次,當我運行我的程序時,它凍結了,我不能點擊任何按鈕,甚至關閉它,因爲窗體凍結。我怎樣才能找到錯誤是在哪裏有時凍結程序

在其他時候,當我退出時(表格關閉),程序就凍結了。 我試圖添加嘗試和捕捉到每一種方法,但它永遠不會停在那裏。

這是我的Form1的頂部和構造:

public partial class Form1 : Form 
    { 
     private bool quitwithtimer; 
     private int y; 
     private int x; 
     private IntPtr ID; 
     private int counter; 
     private int minutes; 
     private int seconds; 
     private DateTime dt; 
     [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     internal static extern bool SetLocalTime(ref SYSTEMTIME lpSystemTime); 

     [StructLayout(LayoutKind.Sequential)] 
     internal struct SYSTEMTIME 
     { 
      public ushort wYear; 
      public ushort wMonth; 
      public ushort wDayOfWeek; // ignored for the SetLocalTime function 
      public ushort wDay; 
      public ushort wHour; 
      public ushort wMinute; 
      public ushort wSecond; 
      public ushort wMilliseconds; 
     } 

     private int day; 
     private int month; 
     private int year; 
     private int hour; 
     private int minute; 

     public Form1() 
     { 
      InitializeComponent(); 

      label1.ForeColor = Color.Red; 
      label1.Text = "Test"; 
      label1.Font = new Font(label1.Font.FontFamily, label1.Font.Size + 8f, label1.Font.Style); 
      TimerCount.Text = "00:00"; 
      quitwithtimer = false; 
      x = Screen.PrimaryScreen.Bounds.Bottom - this.Width * 2; 
      y = Screen.PrimaryScreen.Bounds.Bottom - this.Height * 2; 
      counter = x; 
      ID = this.Handle; //get handle of form 
      minutes = 5; 
      seconds = 0; 
     } 

     [DllImport("user32.dll", SetLastError = true)] 
     internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); 

可能是這其中的DllImport使問題有時?

我有這種方法來獲取當前的時間和日期,但是當程序凍結時它從來沒有得到捕獲。

public static 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); 
      socket.Receive(ntpData); 
      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(); 
     } 

     // stackoverflow.com/a/3294698/162671 
     static uint SwapEndianness(ulong x) 
     { 
      return (uint)(((x & 0x000000ff) << 24) + 
          ((x & 0x0000ff00) << 8) + 
          ((x & 0x00ff0000) >> 8) + 
          ((x & 0xff000000) >> 24)); 
     } 

當運行程序時,以及在大多數情況下退出程序時,有時會使程序凍結一次或兩次。

private void Form1_FormClosing(object sender, FormClosingEventArgs e) 
     { 
      try 
      { 
       if (MessageBox.Show("Are you sure you want to close the form?", "Close Form", 
        MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) 
       { 
        e.Cancel = true; 
       } 
       else 
       { 
        timer1.Enabled = false; 
        timer2.Enabled = false; 
        ChangeTimeOriginal(); 
       } 
      } 
      catch (Exception err) 
      { 
       MessageBox.Show("Error" + err.ToString()); 
      } 
     } 

ChangeTimeOriginal()

private void ChangeTimeOriginal() 
     { 
      try 
      { 
       dt = GetNetworkTime(); 
       day = dt.Day; 
       month = dt.Month; 
       year = dt.Year; 
       hour = dt.Hour; 
       minute = dt.Minute; 
       SYSTEMTIME time = new SYSTEMTIME(); 
       time.wDay = (ushort)day; 
       time.wMonth = (ushort)month; 
       time.wYear = (ushort)year; 
       time.wHour = (ushort)hour; 
       time.wMinute = (ushort)minute; 

       if (!SetLocalTime(ref time)) 
       { 
        // The native function call failed, so throw an exception 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 
       } 
      } 
      catch (Exception err) 
      { 
       MessageBox.Show("Error" + err.ToString()); 
      } 
     } 

我怎麼能發現問題?

編輯**

這是所有我看到的在右下角的調用堆棧窗口當程序凍結,當我做了暫停。

它到了:socket.Receive(ntpData); 在GetNetworkTime()方法中。

這是我目前看到的調用堆棧窗口:

[External Code] 
> TestDateTime.exe!TestDateTime.Form1.GetNetworkTime() Line 122 + 0xd bytes C# 
    TestDateTime.exe!TestDateTime.Form1.ChangeTimeOriginal() Line 272 + 0xe bytes C# 
    TestDateTime.exe!TestDateTime.Form1.Form1_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e) Line 225 + 0x8 bytes C# 
    [External Code] 
    TestDateTime.exe!TestDateTime.Program.Main() Line 19 + 0x1d bytes C# 
    [External Code] 
+6

您是否試過在調試器中暫停執行(凍結過程中)並查看堆棧跟蹤? – Cameron

+1

@Cameron你在開玩笑嗎?在這種情況下,我從來沒有想過要這樣做。好主意。 – Khan

回答

4

它看起來像你的應用程序被凍結的原因是因爲你打電話給GetNetworkTime()這又使得IO阻塞調用時間到服務器。您應該考慮重新處理此代碼,以便在工作線程上執行這些IO阻塞調用。在工作線程上獲取結果後,您可以通過Invoke()BeginInvoke()結構將此數據傳遞迴UI線程。看看this tutorial這應該有所幫助。

+0

好吧,我使用了暫停時建議,當它凍結,並停止在ine:socket.Receive(ntpData);在GetNetworkTime()方法中。但它沒有顯示任何異常或錯誤信息。我如何知道問題是什麼?也許我需要將BeginInvoke()添加到此GetNetworkTime()方法中的每一行? – user2760148

+0

我如何看這個線堆棧跟蹤?這條線塗綠色。在Call Stack窗口的右下角,我看到:> \t TestDateTime.exe!TestDateTime.Form1.GetNetworkTime()Line 122 + 0xd bytes但是我找不到任何堆棧跟蹤選項。 – user2760148

+0

我剛剛更新了我的問題。仍然不知道該怎麼做來解決它。如果這是造成問題的唯一線路?在GetNetworkTime()方法的每一行上使用BeginInvoke()方法? – user2760148