0

I have a method that goes through a very large xml. It takes a while to process so I was thinking of applying Parallel programming into it to make it fast. I am however new to this parallel programming and have no idea yet how. Is the ff. method below applicable to parallel programming? Thanks in advance for your help.

public OpsCategoryList FilterAvailableItemCategory(string xmlCategory, string categoryID)
        {

            XmlDocument categoryXML = new XmlDocument();
            categoryXML.LoadXml(xmlCategory);
            OpsCategoryList ol = new OpsCategoryList();

            try
            {
                foreach (XmlNode x in categoryXML.SelectSingleNode("//CategoryList").SelectNodes("Category[@SuperParentOID='" + categoryID+ "'][@IsLeafFlag='1'][@IsHiddenFlag='0']"))
                {
                    OpsCategory b = new OpsCategory();
                    b.CategoryOID = x.Attributes["CategoryOID"].Value;
                    b.ParentOID = x.Attributes["ParentOID"].Value;

                    OpsItems oi = new OpsItems();
                    oi = LoadOpsItems(b.CategoryOID);
                    if (oi.Items == "")
                    {
                        x.Attributes["IsHiddenFlag"].Value = "1";
                    }
                }

                ol.categoryList = categoryXML.InnerXml;

            }
            catch (Exception ex)
            {
                ol.Error = "FilterAvailableItemCategory() web method failed on call to dbHelper.GetDataSet - " + ex.Message;
            }
            return ol;
        }

this is the LoadOpsItems method

public OpsItems LoadOpsItems(string categoryOID)
        {
            //get ops config info
            OpsConfig oc = new OpsConfig();
            oc = GetOpsConfigInfo();

            //get ops suppliers
            DataSet ds = null;
            Hashtable param = new Hashtable();

            #region SQL Code
            string sqlStr = @"exec DBO.uspOpsSupplierSelect @InternalEntityID='" + base.PmcID + "', @InternalUserID='" + base.UserID +
                      "', @InternalSiteID='" + base.SiteID + "', @IVPC_Name='', @IVPC_Code=''";
            #endregion

            OpsItems oi = new OpsItems();
            OpsSuppliers ap = new OpsSuppliers();
            XmlDocument suppliers = new XmlDocument();
            string tempSupplierXML = "<root>";
            XmlDocument items = new XmlDocument();
            string returnXML = "";

            try
            {
                dbHelper.Entity = xSiteDB.DBEntity.Site;
                ds = dbHelper.GetDataSet(sqlStr, param, "Select");
                Array.Resize(ref ap.Sup, ds.Tables[0].Rows.Count);
                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    #region Field assignment
                    Suppliers tr = new Suppliers();
                    tempSupplierXML += "<Row sosID='" + ds.Tables[0].Rows[i]["sosID"].ToString() + "' ";
                    tempSupplierXML += "sosSupplierOID='" + ds.Tables[0].Rows[i]["sosSupplierOID"].ToString() + "' ";
                    tempSupplierXML += "sosSupplierName='" + ds.Tables[0].Rows[i]["sosSupplierName"].ToString() + "' ";
                    tempSupplierXML += "sosSupplierCode='" + ds.Tables[0].Rows[i]["sosSupplierCode"].ToString() + "' ";
                    tempSupplierXML += "Cnt='" + ds.Tables[0].Rows[i]["Cnt"].ToString() + "' />";
                    #endregion
                }

                tempSupplierXML += "</root>";
                suppliers.LoadXml(tempSupplierXML);

                #region build http request
                string XML = "<Mxml Version='1.0'>" +
                                "<TradingPartner>" +
                                    "<PartnerName>" + oc.socPartnerName + "</PartnerName>" +
                                    "<Identity>" + oc.socIdentity + "</Identity>" +
                                   "</TradingPartner>" +
                                   "<PurchaseGroup>" +
                                       "<GroupName></GroupName>" +
                                       "<GroupCode>" + oc.socGroupCode + "</GroupCode>" +
                                          "<Address>" +
                                              "<Attention1/>" +
                                              "<Attention2/>" +
                                              "<Address1></Address1>" +
                                              "<Address2></Address2>" +
                                              "<Address3/>" +
                                              "<City></City>" +
                                              "<State></State>" +
                                              "<PostalCode></PostalCode>" +
                                              "<Country></Country>" +
                                              "<PhoneNumber/>" +
                                              "<FaxNumber/>" +
                                              "<EmailAddress/>" +
                                          "</Address>" +
                                      "</PurchaseGroup>" +
                                      "<Request>" +
                                          "<GetCategoryProductRequest>" +
                                              "<CompanyCode>" + oc.socCompanyCode + "</CompanyCode>" +
                                              "<PropertyCode></PropertyCode>" +
                                              "<SupplierCodeList>";
                                                    foreach (XmlNode x2 in suppliers.SelectSingleNode("root").SelectNodes("Row"))
                                                    {
                                                        XML += "<SupplierCode>" + x2.Attributes["sosSupplierCode"].Value + "</SupplierCode>";
                                                    }
                                XML += "</SupplierCodeList>" +
                                            "<CategoryOID>" + categoryOID + "</CategoryOID>" +
                                            "<PageSize> 999 </PageSize>" +
                                            "<PageNumber> 1 </PageNumber>" +
                                        "</GetCategoryProductRequest>" +
                                    "</Request>" +
                                "</Mxml>";
                #endregion

                #region pass xml to ops
                WebRequest wr = WebRequest.Create(oc.socOpsURL);
                wr.Method = "POST";
                byte[] byteArray = Encoding.UTF8.GetBytes(XML);
                wr.ContentType = "application/x-www-form-urlencoded";
                wr.ContentLength = byteArray.Length;
                Stream wrRequest = wr.GetRequestStream();
                wrRequest.Write(byteArray, 0, byteArray.Length);
                wrRequest.Close();
                Stream wrResponse = wr.GetResponse().GetResponseStream();
                StreamReader sr = new StreamReader(wrResponse);
                string postResponse = sr.ReadToEnd();
                sr.Close();
                wrResponse.Close();
                #endregion

                items.LoadXml(postResponse);
                returnXML += items.SelectSingleNode("//ProductList").InnerXml;

                oi.Items = returnXML;

            }
            catch (Exception ex)
            {
                oi.Error = "LoadOpsItems() web method failed on call to dbHelper.GetDataSet - " + ex.Message;
            }
            return oi;
        }
  • If the time is spent on the foreach then you can parallelilze it, if the time is spent in the load (most probably) then you cant. – Ignacio Soler Garcia Jun 30 '16 at 13:16
  • 1
    What is the question? are you asking if it would be possible to write this code using parallelism? If that is the question then the answer would be yes, you can write it to use parallel processing. I suggest you look at https://msdn.microsoft.com/en-us/library/dd537609(v=vs.110).aspx or any of the other many resources found on google for the Task Parallel Library. – Jacobr365 Jun 30 '16 at 13:17
  • 1
    Does the order of processing of specific XML tags matter for your particular application? It also looks like you're loading the full XML before processing. Perhaps you can stream with XmlReader? – JamesFaix Jun 30 '16 at 13:17
  • the order does not matter. i just wanna send nodes 1-10 to be processed simultaneously with 11-20 and son on and so forth..The time is mostly spent on the foreach since there are about 1000+ rows – ifallelsefailthenstackoverflow Jun 30 '16 at 13:19
  • Can `LoadOpsItems` handle more than one thread calling it at once? For example does it use any class level SqlConnections or DbContexts? – Scott Chamberlain Jun 30 '16 at 13:24
  • 2
    Writing parallel processing code that all waits on the same I/O resource (one xml file) is rather pointless. You would be better off investigating streaming the data and processing it in small chunks. Have a look at `XmlReader` instead of `XmlDocument`. – Christian Hayter Jun 30 '16 at 13:28
  • LoadOpsItems is basically just an http request to something. Not sure if it can handle more than one thread calling it at once. – ifallelsefailthenstackoverflow Jun 30 '16 at 13:31
  • 1
    Have you run a profiler on your code to find out that the loop actually is the slow part, or are you just assuming that the loop is the slow part because it logically makes sense that that is the only possible slow part? There is a free profiler built in to Visual Studio, use that and post the actual numbers of how long the parts of the function took. Also post the code for `LoadOpsItems` so we can see if it is safe to call in parallel or not. – Scott Chamberlain Jun 30 '16 at 13:32
  • I have edited and added the LoadOpsItems method – ifallelsefailthenstackoverflow Jun 30 '16 at 13:38
  • Hi you should read this question about the differences between the types of multithreading, trust me it's worth reading http://stackoverflow.com/questions/4844637/what-is-the-difference-between-concurrency-parallelism-and-asynchronous-methods – Oscar Ortiz Jun 30 '16 at 13:42
  • What says a Profiler? Where is the bottleneck? – Alexander Petrov Jun 30 '16 at 13:54
  • the bottleneck is in the LoadOpsItems – ifallelsefailthenstackoverflow Jun 30 '16 at 14:10

0 Answers0