代码之家  ›  专栏  ›  技术社区  ›  RoyValentine

WinForm计时器访问文本框

  •  0
  • RoyValentine  · 技术社区  · 14 年前

    因此,我试图从snmpsharpnet创建一个使用SNMP的基本WinForm应用程序。

    我有两个按钮“Eye”和“Jitter”,当按下其中一个按钮时,计时器就会启动,每分钟在计时器处理程序中执行SNMP代码。

    我正试图从计时器处理程序将SNMP输出写入文本框,但我所尝试的一切要么导致线程异常,要么在退出程序时导致持续运行的进程。

    我已经尝试了很多不同的方法来修复这两个错误,我可能会把一切都搞砸,但以下是我的代码:

    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 = false, sec = false, eye = false, jitter = false;
            static string ipAdd = "";
            static System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
            static int alarmCounter = 1;
            static bool exitFlag = false;
            static TextBox textbox;
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                textbox = outputBox;
            }
    
            private void IPtext_TextChanged(object sender, EventArgs e)
            {
                ipAdd = IPtext.Text;
            }
    
            private void stopButton_Click(object sender, EventArgs e)
            {
                stop = true;
                timer.Stop();
            }
    
            // This is the method to run when the timer is raised.
            private static void TimerEventProcessor(Object myObject,
                                                EventArgs myEventArgs)
            {
                timer.Stop();
    
                // If stop button has not been pressed then continue timer.
                if (stop == false)
                {
                    textbox.Clear();
                    // Restarts the timer and increments the counter.
                    alarmCounter += 1;
                    timer.Enabled = true;
                    /*
                    textbox.Invoke(
                        new MethodInvoker(
                            delegate { textbox.AppendText("fsjdaò"); }));
                    */
                    System.IO.StreamWriter file;
                    if (eye == true)
                    {
                        file = new System.IO.StreamWriter("c:/Users/bshellnut/Desktop/Eye.txt", true);
                    }
                    else
                    {
                        file = new System.IO.StreamWriter("c:/Users/bshellnut/Desktop/Jitter.txt", 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);
                            //textbox.Text = "";
                        }
                        catch (SnmpSharpNet.SnmpException)
                        {
                            textbox.Invoke(
                                new MethodInvoker(
                                    delegate { textbox.AppendText("Could not connect to the IP Provided."); }));
                            timer.Stop();
                            //outputBox.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
                                /*Console.WriteLine("Error in SNMP reply. Error {0} index {1}",
                                    result.Pdu.ErrorStatus,
                                    result.Pdu.ErrorIndex);*/
                                    textbox.Invoke(
                                        new MethodInvoker(
                                            delegate { textbox.AppendText("Error in SNMP reply. " + "Error " + result.Pdu.ErrorStatus + " index " + result.Pdu.ErrorIndex); }));
                                //outputBox.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))
                                    {
                                        /*Console.WriteLine("{0} ({1}): {2}",
                                            v.Oid.ToString(),
                                            SnmpConstants.GetTypeName(v.Value.Type),
                                            v.Value.ToString());*/
    
                            textbox.Invoke(
                                                new MethodInvoker(
                                                     delegate { textbox.AppendText(v.Oid.ToString() + " " + SnmpConstants.GetTypeName(v.Value.Type) +
                                                " " + v.Value.ToString() + Environment.NewLine); }));
    
                                        //outputBox.Text += v.Oid.ToString() + " " + SnmpConstants.GetTypeName(v.Value.Type) +
                                           //" " + v.Value.ToString() + Environment.NewLine;
    
                        file.WriteLine(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.Invoke(
                                new MethodInvoker(
                                    delegate { textbox.AppendText("No response received from SNMP agent."); }));
                            //outputBox.Text = "No response received from SNMP agent.";
                        }
                    }
                    target.Close();
                    file.Close();
                }
                else
                {
                    // Stops the timer.
                    exitFlag = true;
                }
            }
    
            private void eyeButton_Click(object sender, EventArgs e)
            {
                outputBox.Text = "Connecting...";
                eye = true;
                jitter = false;
                stop = false;
    
                timer.Tick += new EventHandler(TimerEventProcessor);
    
                // Sets the timer interval to 5 seconds.
                timer.Interval = 5000;
                timer.Start();
    
                // Runs the timer, and raises the event.
                while (exitFlag == false)
                {
                    // Processes all the events in the queue.
                    Application.DoEvents();
                }
            }
    
            private void jitterButton_Click(object sender, EventArgs e)
            {
                outputBox.Text = "Connecting...";
                eye = false;
                jitter = true;
                stop = false;
    
                timer.Tick += new EventHandler(TimerEventProcessor);
    
                // Sets the timer interval to 5 seconds.
                timer.Interval = 5000;
                timer.Start();
    
                // Runs the timer, and raises the event.
                while (exitFlag == false)
                {
                    // Processes all the events in the queue.
                    Application.DoEvents();
                }
            }
    
            private void Seconds_CheckedChanged(object sender, EventArgs e)
            {
                min = false;
                sec = true;
            }
    
            private void Minutes_CheckedChanged(object sender, EventArgs e)
            {
                min = true;
                sec = false;
            }
        }
    }
    
    2 回复  |  直到 14 年前
        1
  •  1
  •   Jon Senchyna    14 年前

    我相信您在UI线程上遇到了死锁。

    TimerEventProcessor() 由您的实例调用 System.Windows.Forms.Timer ,它在UI线程上运行。当计时器关闭时,我相信它会将一条消息放入UI线程的消息队列,以调用 计时器事件处理器() 方法该方法依次调用 textbox.Invoke() ,将另一条消息放入队列,然后 等待处理 。

    您的UI线程现在被卡住了,因为它正在处理消息,但必须等待另一条消息被处理后才能继续。对的呼叫 Application.DoEvents() 你没有好处,因为一旦你的程序进入,他们就不会被调用 计时器事件处理器() 。(它们也是不必要的,因为你的按钮点击处理程序无论如何都不会阻塞UI线程。)

    由于计时器在UI线程上运行,因此可以取消 textbox.Invoke() 呼叫和仅访问 textbox 直接地

    摘要:

    1. 将您的呼叫替换为 textbox.Invoke() 可直接访问 文本框
    2. 删除对的呼叫 Application.DoEvents()

    注: 如果你得到 Application.DoEvents() 来自的逻辑 MSDN example 对于使用定时器,他们把它放在那里,这样一旦Main函数完成,应用程序就不会退出。

    更新: 您可以通过将您的呼叫替换为 textbox.Invoke 使用以下代码。如果这段代码有效,那么您肯定会遇到UI消息队列死锁问题。此外,如果这确实解决了这个问题,我不建议将其作为解决方案,而是如上所述解决死锁问题。

    // Make the request asynchronously
    System.IAsyncResult asyncResult = textbox.BeginInvoke(
        new MethodInvoker(
            delegate { /* insert delegate code here */ }));
    
    // Process the message queue until this request has been completed
    while(!asyncResult.IsCompleted) Application.DoEvents();
    
    // Clean up our async request
    textbox.EndInvoke(asyncResult);
    

    由于您的代码似乎可以正常工作,因此可以忽略上面的测试代码。

        2
  •  0
  •   Amiram Korach    14 年前

    你的问题与计时器和所有 Invoke 您使用的语句不是必需的。这个 System.Windows.Forms.Timer 类在UI线程中操作。看这里: http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx