2012-08-06 78 views
2

我寫一個WinForm應用程序使用SNMP或者調用每30秒或1分鐘。的WinForm隨着多個定時器

我有一個計時器工作叫我的SNMP命令,但我想補充一點,顯示在操作過程中所經過的總時間的texbox計數器。

有我有那麼這裏的許多問題,是一個列表:

  1. 我希望我的SNMP計時器「計時器」等待分配的時間,所以我有它在3秒會關閉,然後才重新執行改變我的處理程序的時間間隔。但是這有時會讓計時器關閉多次,這不是我想要的。
  2. 每次'計時器'關閉,我的SNMP調用執行我的計數器計時器'appTimer'變得不同步。我嘗試了一下在哪裏檢查它是否在另一個處理程序中,然後將計時器跳到適當的時間。哪些工作,但我覺得這使得它太複雜。
  3. 我的最後一個問題,我知道的,發生在我使用我的停止按鈕不完全退出應用程序停止我的應用程序。當我開始另一次運行時,兩個定時器之間的時間變得更大,並且由於某種原因,我的計數定時器「appTimer」開始以兩倍的速度開始計數。

我希望這說明不是太混亂,但這裏是我的代碼反正:

using System; 
using System.Net; 
using SnmpSharpNet; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public static bool stop = false; 
     static bool min = true, eye = false, firstTick = false; 
     static string ipAdd = "", fileSaveLocation = ""; 
     static System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); 
     static System.Windows.Forms.Timer appTimer = new System.Windows.Forms.Timer(); 
     static int alarmCounter = 1, hours = 0, minutes = 0, seconds = 0, tenthseconds = 0, count = 0; 
     static bool inSNMP = false; 
     static TextBox textbox, timeTextbox; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      textbox = outputBox; 
      timeTextbox = timeBox; 
      ipAdd = "192.168.98.107"; 
      fileSaveLocation = "c:/Users/bshellnut/Desktop/Eye.txt"; 
      min = true; 
      inSNMP = false; 
     } 

     private void IPtext_TextChanged(object sender, EventArgs e) 
     { 
      ipAdd = IPtext.Text; 
     } 

     private void stopButton_Click(object sender, EventArgs e) 
     { 
      stop = true; 
      timer.Stop(); 
      appTimer.Stop(); 
      count = 0; 
      hours = minutes = seconds = tenthseconds = 0; 
      inSNMP = false; 
     } 

     // This is the method to run when the timer is raised. 
     private static void TimerEventProcessor(Object myObject, 
               EventArgs myEventArgs) 
     { 
      inSNMP = true; 
      timer.Stop(); 

      if (firstTick == true) 
      { 
       // Sets the timer interval to 60 seconds or 1 second. 
       if (min == true) 
       { 
        timer.Interval = 1000 * 60; 
       } 
       else 
       { 
        timer.Interval = 1000 * 30; 
       } 
      } 

      // Displays a message box asking whether to continue running the timer. 
      if (stop == false) 
      { 
       textbox.Clear(); 
       // Restarts the timer and increments the counter. 
       alarmCounter += 1; 
       timer.Enabled = true; 

       System.IO.StreamWriter file; 
       //if (eye == true) 
       //{ 
        file = new System.IO.StreamWriter(fileSaveLocation, true); 
       /*} 
       else 
       { 
        file = new System.IO.StreamWriter(fileSaveLocation, true); 
       }*/ 

       // SNMP community name 
       OctetString community = new OctetString("public"); 

       // Define agent parameters class 
       AgentParameters param = new AgentParameters(community); 
       // Set SNMP version to 2 (GET-BULK only works with SNMP ver 2 and 3) 
       param.Version = SnmpVersion.Ver2; 
       // Construct the agent address object 
       // IpAddress class is easy to use here because 
       // it will try to resolve constructor parameter if it doesn't 
       // parse to an IP address 
       IpAddress agent = new IpAddress(ipAdd); 

       // Construct target 
       UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1); 

       // Define Oid that is the root of the MIB 
       // tree you wish to retrieve 
       Oid rootOid; 
       if (eye == true) 
       { 
        rootOid = new Oid("1.3.6.1.4.1.128.5.2.10.14"); // ifDescr 
       } 
       else 
       { 
        rootOid = new Oid("1.3.6.1.4.1.128.5.2.10.15"); 
       } 

       // This Oid represents last Oid returned by 
       // the SNMP agent 
       Oid lastOid = (Oid)rootOid.Clone(); 

       // Pdu class used for all requests 
       Pdu pdu = new Pdu(PduType.GetBulk); 

       // In this example, set NonRepeaters value to 0 
       pdu.NonRepeaters = 0; 
       // MaxRepetitions tells the agent how many Oid/Value pairs to return 
       // in the response. 
       pdu.MaxRepetitions = 5; 

       // Loop through results 
       while (lastOid != null) 
       { 
        // When Pdu class is first constructed, RequestId is set to 0 
        // and during encoding id will be set to the random value 
        // for subsequent requests, id will be set to a value that 
        // needs to be incremented to have unique request ids for each 
        // packet 
        if (pdu.RequestId != 0) 
        { 
         pdu.RequestId += 1; 
        } 
        // Clear Oids from the Pdu class. 
        pdu.VbList.Clear(); 
        // Initialize request PDU with the last retrieved Oid 
        pdu.VbList.Add(lastOid); 
        // Make SNMP request 
        SnmpV2Packet result; 
        try 
        { 
         result = (SnmpV2Packet)target.Request(pdu, param); 
        } 
        catch (SnmpSharpNet.SnmpException) 
        { 
         timer.Stop(); 
         textbox.Text = "Could not connect to the IP Provided."; 
         break; 
        } 
        // You should catch exceptions in the Request if using in real application. 

        // If result is null then agent didn't reply or we couldn't parse the reply. 
        if (result != null) 
        { 
         // ErrorStatus other then 0 is an error returned by 
         // the Agent - see SnmpConstants for error definitions 
         if (result.Pdu.ErrorStatus != 0) 
         { 
          // agent reported an error with the request 
          textbox.Text = "Error in SNMP reply. " + "Error " + result.Pdu.ErrorStatus + " index " + result.Pdu.ErrorIndex; 

          lastOid = null; 
          break; 
         } 
         else 
         { 
          // Walk through returned variable bindings 
          foreach (Vb v in result.Pdu.VbList) 
          { 
           // Check that retrieved Oid is "child" of the root OID 
           if (rootOid.IsRootOf(v.Oid)) 
           { 
            count++; 
            textbox.Text += "#" + count + " " + v.Oid.ToString() + " " + SnmpConstants.GetTypeName(v.Value.Type) + 
                " " + v.Value.ToString() + Environment.NewLine; 

            file.WriteLine("#" + count + ", " + v.Oid.ToString() + ", " + SnmpConstants.GetTypeName(v.Value.Type) + 
                ", " + v.Value.ToString(), true); 
            if (v.Value.Type == SnmpConstants.SMI_ENDOFMIBVIEW) 
             lastOid = null; 
            else 
             lastOid = v.Oid; 
           } 
           else 
           { 
            // we have reached the end of the requested 
            // MIB tree. Set lastOid to null and exit loop 
            lastOid = null; 
           } 
          } 
         } 
        } 
        else 
        { 
         //Console.WriteLine("No response received from SNMP agent."); 
         textbox.Text = "No response received from SNMP agent."; 
         //outputBox.Text = "No response received from SNMP agent."; 
        } 
       } 
       target.Close(); 
       file.Close(); 
      } 
      else 
      { 
       // Stops the timer. 
       //exitFlag = true; 
       count = 0; 
      } 
     } 

     private static void ApplicationTimerEventProcessor(Object myObject, 
               EventArgs myEventArgs) 
     { 

      tenthseconds += 1; 

      if (tenthseconds == 10) 
      { 
       seconds += 1; 
       tenthseconds = 0; 
      } 

      if (inSNMP && !firstTick) 
      { 
       if (min) 
       { 
        seconds = 60; 
       } 
       else 
       { 
        textbox.Text += "IN 30 SECONDS!!!"; 
        if (seconds < 30) 
        { 
         seconds = 30; 
        } 
        else 
        { 
         seconds = 60; 
        } 
       } 
      } 

      if(seconds == 60) 
      { 
       seconds = 0; 
       minutes += 1; 
      } 

      if(minutes == 60) 
      { 
       minutes = 0; 
       hours += 1; 
      } 

      timeTextbox.Text = (hours < 10 ? "00" + hours.ToString() : hours.ToString()) + ":" + 
           (minutes < 10 ? "0" + minutes.ToString() : minutes.ToString()) + ":" + 
           (seconds < 10 ? "0" + seconds.ToString() : seconds.ToString()) + "." + 
           (tenthseconds < 10 ? "0" + tenthseconds.ToString() : tenthseconds.ToString()); 
      inSNMP = false; 
      firstTick = false; 
     } 

     private void eyeButton_Click(object sender, EventArgs e) 
     { 
      outputBox.Text = "Connecting..."; 
      eye = true; 
      stop = false; 
      count = 0; 
      hours = minutes = seconds = tenthseconds = 0; 

      timer.Tick += new EventHandler(TimerEventProcessor); 

      timer.Interval = 3000; 
      firstTick = true; 

      appTimer.Tick += new EventHandler(ApplicationTimerEventProcessor); 

      appTimer.Interval = 100; 

      appTimer.Start(); 
      timer.Start(); 
     } 

     private void jitterButton_Click(object sender, EventArgs e) 
     { 
      outputBox.Text = "Connecting..."; 
      eye = false; 
      stop = false; 
      count = 0; 
      hours = minutes = seconds = tenthseconds = 0; 

      timer.Tick += new EventHandler(TimerEventProcessor); 

      timer.Interval = 3000; 
      firstTick = true; 

      appTimer.Tick += new EventHandler(ApplicationTimerEventProcessor); 

      appTimer.Interval = 100; 

      appTimer.Start(); 
      timer.Start(); 
     } 

     private void Seconds_CheckedChanged(object sender, EventArgs e) 
     { 
      min = false; 
     } 

     private void Minutes_CheckedChanged(object sender, EventArgs e) 
     { 
      min = true; 
     } 

     private void exitButton_Click(object sender, EventArgs e) 
     { 
      Application.Exit(); 
     } 

     private void savetextBox_TextChanged(object sender, EventArgs e) 
     { 
      fileSaveLocation = savetextBox.Text; 
     } 
    } 
} 
+2

我懷疑在這種情況下,線程是比定時器更好的替代品。 – 2012-08-06 22:23:45

+1

我強烈建議將你的代碼分成多個方法(甚至是類)。你的'TimerEventProcessor'是通向大... – CodeZombie 2012-08-06 22:47:26

+0

@SimpleCoder我可以並且最終會這樣做,但這並不會改變這些事情發生的事實。 – RoyValentine 2012-08-06 23:03:27

回答

3

這是很容易與一個計時器做。該計時器具有1/10秒的分辨率(大約),可以直接用來更新經過的時間。然後,您可以使用該計時器內的相對耗用時間來觸發您的SNMP事務,並且可以動態地重新安排下一個事務。

這裏有一個簡單的例子

using System; 
using System.Drawing; 
using System.Windows.Forms; 

class Form1 : Form 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new Form1()); 
    } 

    DateTime lastSnmpTime; 
    TimeSpan snmpTime = TimeSpan.FromSeconds(30); 
    DateTime startTime; 
    TextBox elapsedTimeTextBox; 
    Timer timer; 

    public Form1() 
    { 
     timer = new Timer { Enabled = false, Interval = 10 }; 
     timer.Tick += new EventHandler(timer_Tick); 

     elapsedTimeTextBox = new TextBox { Location = new Point(10, 10), ReadOnly = true }; 
     Controls.Add(elapsedTimeTextBox); 
    } 

    protected override void OnLoad(EventArgs e) 
    { 
     base.OnLoad(e); 

     startTime = DateTime.Now; 
     timer.Start(); 
    } 

    void timer_Tick(object sender, EventArgs e) 
    { 
     // Update elapsed time 
     elapsedTimeTextBox.Text = (DateTime.Now - startTime).ToString("g"); 

     // Send SNMP 
     if (DateTime.Now - lastSnmpTime >= snmpTime) 
     { 
      lastSnmpTime = DateTime.Now; 

      // Do SNMP 

      // Adjust snmpTime as needed 
     } 
    } 
} 

之初更新Q &一個

有了這個代碼,定時器觸發一次在那裏後,我 按下停止按鈕,並調用timer.Stop ()然後按我的開始 按鈕計時器不會觸發,直到大約12秒鐘後。將 重置DateTimes修復此問題?

當用戶按下開始按鈕時,設置lastSnmpTime = DateTime.MinValue。這會導致(DateTime.Now - lastSnmpTime)的TimeSpan超過2000年,所以它會比snmpTime大,並會立即觸發。

此外,我在文本框中的輸出時間如下所示:0:00:02.620262。 這是爲什麼?有沒有辦法讓它只顯示0:00:02.62?

當您減去兩個DateTime值時,結果是一個TimeSpan值。我使用"g"standard TimeSpan formatting string。您可以使用@"d\:hh\:mm\:ss\.ff"custom TimeSpan formatting string得到天數:小時:分鐘:秒。小數(2位小數)。

當計算機運行 超過9小時時,計時器還會繼續並打印到文本框中?因爲我打算有這個運行24個小時+

如果您使用「d」自定義格式顯示的天數,它將爲TimeSpan.MaxValue運行稍微超過10675199天,這是多29,000年。

+0

謝謝。這似乎工作得很好。我知道使用DateTime有更好的方法,但我找不到很多好的例子。我確實有幾個問題。使用此代碼,定時器會在開始時觸發一次,在按下停止按鈕並調用timer.Stop()之後,然後按下我的開始按鈕,定時器在大約12秒鐘後纔會觸發。將重置DateTimes修復此問題?當計時器運行9個小時以上時,計時器還會繼續並打印到文本框中?因爲我計劃在24小時以內運行。 – RoyValentine 2012-08-07 16:57:55

+0

此外,我在文本框中的輸出時間如下所示:0:00:02.620262。這是爲什麼?有沒有辦法讓它只顯示0:00:02.62? – RoyValentine 2012-08-07 17:08:49

+0

@RoyValentine我上面編輯回答你的問題。 – Tergiver 2012-08-07 19:57:10