0

そこで、SNMPを使用する基本的なWinFormアプリケーションをsnmpsharpnetから作成しようとしています。

「目」と「ジッター」の2つのボタンがあり、1つを押すとタイマーが開始し、タイマーハンドラー内で1分ごとにSNMPコードを実行します。

タイマーハンドラーからSNMP出力をテキストボックスに書き込もうとしていますが、プログラムを終了すると、スレッド例外または継続的な実行プロセスが発生します。

私はこれらの2つのエラーを修正するために非常に多くの異なることを試みたので、すべてを台無しにしている可能性がありますが、ここに私が持っているコードがあります:

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;
        }
    }
}
4

2 に答える 2

1

UIスレッドでデッドロックが発生していると思います。

TimerEventProcessor()System.Windows.Forms.TimerUIスレッドで実行されるのインスタンスによって呼び出されます。タイマーが切れると、UIスレッドのメッセージキューにメッセージが入れられ、TimerEventProcessor()メソッドが呼び出されると思います。次に、そのメソッドはを呼び出しますtextbox.Invoke()。これにより、別のメッセージがキューに入れられ、処理されるのを待ちます

UIスレッドは、メッセージの処理中のためスタックしていますが、続行するには、別のメッセージが処理されるまで待機する必要があります。あなたのプログラムが入ると彼らは呼ばれないので、あなたをするための呼び出しはApplication.DoEvents()良くありませんTimerEventProcessor()。(ボタンクリックハンドラーがUIスレッドをブロックしないため、これらも不要です。)

textbox.Invoke()タイマーはUIスレッドで実行されるため、呼び出しを取り除き、textbox直接アクセスすることができます。

概要:

  1. textbox.Invoke()への通話をへの直接アクセスに置き換えますtextbox
  2. にあなたの呼び出しを削除しますApplication.DoEvents()

注:MSDNApplication.DoEvents()の例からタイマーを使用するためのロジックを取得した場合は、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);

コードは機能しているように見えるので、上記のテストコードは無視してかまいません。

于 2012-08-06T16:15:20.090 に答える
0

問題はタイマーとは関係がなく、Invoke使用するすべてのステートメントは必要ありません。クラスはSystem.Windows.Forms.TimerUIスレッドで動作します。ここを見てください:http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx

于 2012-08-06T16:09:42.633 に答える