C# 多线程编程

C# 多线程编程,c#,multithreading,C#,Multithreading,我已经编写了一个控制台应用程序,从EMp_Raw中获取前50条记录,其中包含empname、EMPDailLink、InsertedDate、parsedstatus,应该从客户网站转到员工的每个链接,通过html抓取,获取详细信息并保存到数据库。我每分钟都使用任务调度器运行此作业。我能够成功地做到这一点,但经理希望它是多线程的,以使它更快。下面是我尝试过的,我插入了最后一条记录50次,而不是50条唯一的记录 namespace Emp_Detail { class detEmp

我已经编写了一个控制台应用程序,从EMp_Raw中获取前50条记录,其中包含empname、EMPDailLink、InsertedDate、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 reader循环中的内容

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个不同的对象,每个对象都有各自的内容。

您使用的是什么版本的C?顺便说一句,按照惯例,类名、getter和setter以及方法都是大写的。你能展示一下运行正常的原始版本吗?在原始代码中,我没有任何线程代码,如果!string.IsNullOrEmptyempname{InsertDetailsempname,DetailLink;}Iam正在使用.Net 4.5 framework。是否要加快代码速度?摆脱线程。睡觉。