2014-07-26 3 views
0

EMp_Raw (empname, empdetaillink, inseteddate, parsedstatus 포함)에서 상위 50 개 레코드를 얻는 콘솔 응용 프로그램을 작성했으며 클라이언트 웹 사이트에서 직원의 각 링크로 가서 'html'을 크롤링하고 세부 정보를 얻고 DB에 저장하십시오. 매분마다 작업 스케줄러를 사용하여이 작업을 실행합니다. 나는 성공적으로 그 일을 할 수 있었지만, 관리자는 그것을 더 빨리 만들기 위해 다중 스레드를 원한다. 아래는 내가 시도한 것이며 마지막 레코드를 50 번 삽입하고 50 개의 고유 레코드를 삽입하지 않습니다.다중 스레드 프로그래밍 C#

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(); 

        } 

       } 
      } 
+2

어떤 버전의 C#을 사용하고 있습니까? 그리고 컨벤션 클래스 명, getter, setter 및 메소드에 의한 BTW는 대문자입니다. –

+0

비교를 위해 제대로 작동 한 원본 버전을 표시 할 수 있습니까? – merlin2011

+0

원래 코드에서 스레딩 코드가없는 경우 if (! string.IsNullOrEmpty (empname)) { InsertDetails (empname, DetailLink); } – newbieCSharp

답변

2

단일 개체를 만듭니다.

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 개의 서로 다른 개체가 있으며 각 개체마다 각각 다른 콘텐츠가 있습니다.