異世界


2014年8月7日 星期四

SNMP-Walk應用_多工簡單化 : async & await

參考資料 : http://www.codeproject.com/Articles/660482/Insides-Of-Async-Await 

在一個 async Methard ( )  中,程式會在 await 中等待新的線程完成,但主線程不阻塞。

該 async Methard ( ) 可多次進入,產生多個線程同時執行。

/* 主線程 */
private async void ThreadMathed()
        {
            txtAnalysisResult.Text = "Please wait while analysing the population.";
 
            try
            {
                int result = await new AnalysisEngine().AnalyzePopulationAsync();
                txtAnalysisResult.Text = result.ToString();
            }
            catch (System.Exception exp)
            {
                txtAnalysisResult.Text = exp.Message + Thread.CurrentThread.Name;
            }
        }
 
/* 子線程 Class */
class AnalysisEngine
    {
        public Task<int> AnalyzePopulationAsync()
        {
            Task<int> task = new Task<int>(AnalyzePopulation);
            task.Start();
 
            return task;
        }
 
        public int AnalyzePopulation()
        {
            //Sleep is used to simulate the time consuming activity.
            Thread.Sleep(10000);
            return new Random().Next(1, 5000);
        }
    }

 


運用到多線程 SNMP Walk : (該程式需使用 SnmpSharpNet.dll )



/* 主線程 */
        private async void button2_Click(object sender, EventArgs e)
        {
            Text = cnt++.ToString();
 
            NmsDevice dev = new NmsDevice();
            dev.IP = txtIP.Text;
            dev = await Pulling(dev, textBox1.Text);
 
            txtAnalysisResult.Text += dev.PullingOidResult + Environment.NewLine;
        }
        private async Task<NmsDevice> Pulling(NmsDevice dev, string oid)
        {
            NmsDevice Dev = new NmsDevice();
            try
            {
                Dev = await new SNMP_Walk(dev, oid).OidPullingAsync();
            }
            catch (System.Exception exp)
            {
                //txtAnalysisResult.Text = exp.Message + Thread.CurrentThread.Name;
                Dev.PullingOidResult = string.Format("No response received from SNMP agent.{0}", Environment.NewLine);
            }
            return Dev;
        }

子線程物件:



public class SNMP_Walk
 {
     /* 建構式 */
     public SNMP_Walk(NmsDevice dev, string oid)
     {
         mDevice = dev;
         OID = oid;
     }
 
     /* 屬性 */
     private NmsDevice mDevice = new NmsDevice();
     private string OID { get; set; }
 
     /* 方法 */
     public Task<NmsDevice> OidPullingAsync()
     {
         /* 一般程式寫法 */
         //Task<NmsDevice> task = new Task<NmsDevice>(SnmpWalk);
         //task.Start();
 
         /* 黏巴達 語法 */
         //Task<NmsDevice> task = Task<NmsDevice>.Factory.StartNew(() => { return SnmpWalk(); });
         //return task;
 
         /* 匿名方式 黏巴達 語法*/
         return Task<NmsDevice>.Factory.StartNew(() => { return SnmpWalk(); });
     }
     private NmsDevice SnmpWalk()
     {
         string IP = mDevice.IP;
 
         List<string> list = new List<string>();
         list = SnmpWalkList(IP, OID);
 
         /* 串接回傳值 */
         mDevice.PullingOidResult = "";
         foreach (string ss in list)
         {
             mDevice.PullingOidResult += string.Format("{0}{1}", ss, Environment.NewLine);
         }
         return mDevice;
     }
     private List<string> SnmpWalkList(string IP, string oid)
     {
         List<string> list = new List<string>();
 
         try
         {
             // SNMP community name
             OctetString community = new OctetString("public");
 
             // Define agent parameters class
             AgentParameters param = new AgentParameters(community);
             // Set SNMP version to 1
             param.Version = SnmpVersion.Ver1;
             // 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(IP);
 
             // 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 = new Oid(oid.Replace("\"", "")); // ifDescr
 
             // 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.GetNext);
 
             #region Loop through results
             while (lastOid != null)
             {
                 // When Pdu class is first constructed, RequestId is set to a random value
                 // that needs to be incremented on subsequent requests made using the
                 // same instance of the Pdu class.
                 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
                 SnmpV1Packet result = (SnmpV1Packet)target.Request(pdu, param);
                 // 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(string.Format("Error in SNMP reply. Error {0} index {1}",
                             result.Pdu.ErrorStatus,
                             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))
                             {
                                 //listBox1.Items.Add(string.Format("{0} ({1}): {2}",
                                 //    v.Oid.ToString(),
                                 //    SnmpConstants.GetTypeName(v.Value.Type),
                                 //    v.Value.ToString()) );
                                 list.Add(string.Format("{0}{1}", v.Value.ToString(), Environment.NewLine));
                                 lastOid = v.Oid;
                             }
                             else
                             {
                                 // we have reached the end of the requested
                                 // MIB tree. Set lastOid to null and exit loop
                                 lastOid = null;
                             }
                         }
                     }
                 }
                 else
                 {
                     list.Add(string.Format("No response received from SNMP agent.{0}", Environment.NewLine));
                 }
             }
             #endregion
 
             target.Close();
             return list;
         }
         catch (Exception ex)
         {
             list.Add(string.Format("No response received from SNMP agent.{0}", Environment.NewLine));
             return list;
         }
     }
 }

沒有留言:

張貼留言