簡體   English   中英

多線程編程C#

[英]multithreaded programming c#

我編寫了一個控制台應用程序,該應用程序從EMp_Raw中獲取前50條記錄(包含empname,empdetaillink,inseteddate,parsedstatus),並且應轉到客戶網站上員工的每個鏈接並通過html進行爬網,並獲取其詳細信息並將其保存到我們的數據庫中。我每分鍾使用任務計划程序運行此作業。 我能夠成功地做到這一點,但經理希望它具有多線程功能以使其更快。 下面是我嘗試過的方法,我將最后一條記錄插入50次,而不是50條唯一記錄。

namespace Emp_Detail
{
    class detEmp 
    {
        private string empname;
        private string empdetlink;
        public detEmp()
        {
        }

        public detEmp(String empname, String empdetlink)
        {

            this.empname = empname;
            this.empdetlink = empdetlink;
        }
        public string getempname()
        {
            return empname;
        }

        public void setempname(string empname)
        {
            this.empname = empname;
        }

        public string getempdetlink()
        {
            return empdetlink;
        }

        public void setempdetlink(string empdetlink)
        {
            this.empdetlink = empdetlink;
        }
    }
    class Program
    {
       static void Main(string[] args)
        {
            detEmp detail = new detEmp() { };
            List<detEmp> d = new List<detEmp>();
            Logger.info("Start Emp details at: "+ DateTime.Now);
            try
            {
                using (SqlConnection connection = new SqlConnection(GetConnectionString()))
                {
                    connection.Open();
                    using (SqlCommand sqlCommandReader = connection.CreateCommand())
                    {
                        sqlCommandReader.CommandText = @"SELECT top 50 empname, empDetailLink, ParsedStatus,InsertedDate  FROM [dbo].[Emp_Raw] (nolock) 
   Where ParsedStatus = 0 and InsertedDate between '2014-07-23 08:30:30.000' and '2014-07-23 08:35:30.000'
                                                     order by InsertedDate";
                        SqlDataReader sqlDataReader = sqlCommandReader.ExecuteReader();
                        if (sqlDataReader.HasRows)//completed
                        {
                            int count = 0;
                            while (sqlDataReader.Read())
                            {
   string DetailLink = sqlDataReader["EmpDetailLink"] == null ? string.Empty : sqlDataReader["EmpDetailLink"].ToString();
                                string empname = sqlDataReader["empname"] == null ? string.Empty : sqlDataReader["empname"].ToString();

                                if (!string.IsNullOrEmpty(empname))
                                {
                                   detail.setempname(empname);
                                   detail.setempdetlink(DetailLink);
                                    d.Add(detail);              
                                }                                         
                           }
                        }
                      }
                }
               //when I print DetailLink using for loop I can see only last record inserted 50 times--not sure why      

                var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 1 }; //Number of cores you have, limits the thread count
                Parallel.ForEach(d, options, i =>
                {
                //THis is a function that pulls out emp info from client website and puts into our db using htmlagilitypack--tested thoroughly works fine
                    InsertDetails(i.getempname(), i.getempdetlink());
                    Thread.Sleep(50);
                });

                using (SqlConnection connection = new SqlConnection(GetConnectionString()))
                {
                    connection.Open();
                    using (SqlCommand sqlCommandReader = connection.CreateCommand())
                    {
                        sqlCommandReader.CommandText = ";WITH CTE AS (SELECT TOP 50 * FROM [dbo].[Emp_Raw] (nolock) where parsedstatus=0  and InsertedDate between '2014-07-23 08:30:30.000' and '2014-07-23 08:35:30.000' ORDER BY InsertedDate) UPDATE CTE SET ParsedStatus=1";
                        sqlCommandReader.ExecuteNonQuery();

                    }

                }
            }

您正在創建一個細節對象。

detEmp detail = new detEmp() { };

...然后在SQL閱讀器循環中重新分配內容;

while (sqlDataReader.Read())
{
...
    if (!string.IsNullOrEmpty(empname))
    {
       detail.setempname(empname);
       detail.setempdetlink(DetailLink);
        d.Add(detail);              
    }                                         

換句話說,您將數據分配給詳細信息,將其添加到集合中,更改詳細信息的內容,然后再次添加...問題是您將相同的對象添加到列表中50次,最后全部包含最后一個行讀取。

您可以做的就是為每次迭代創建一個新的局部對象。

if (!string.IsNullOrEmpty(empname))
{
   detEmp detail = new detEmp() { };
   detail.setempname(empname);
   detail.setempdetlink(DetailLink);
    d.Add(detail);              
}                                         

...這將為您提供列表中的50個不同的對象,每個對象都有各自的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM