2012-07-02 8 views
1
나는 데이터베이스에서 100.000 행을 읽을 필요

,이 코드를 사용리스트로 삽입을 개선하는 방법을 사용하는 멀티 코어

List<elementClass> Listelement = new List<elementClass>(); 
using (DbDataReader reader = cmd.ExecuteReader()) 
{ 
    while (reader .Read()) 
    { 
     elementClass element= new elementClass(); 
     DatabaseClass.ReadFromObject(reader , element); 
     Listelement.Add(element); 
    } 
} 

ReadFromObject :

public static void ReadFromObject(DbDataReader dr, Object obj) 
{ 
    DataTable tableDescriptor = dr.GetSchemaTable(); 

    try 
    { 
     //Id - Identifier 
     obj.GetType().GetProperty("Id").SetValue(obj, dr.GetValue(dr.GetOrdinal("Id")), null); 

     PropertyInfo[] properties = obj.GetType().GetProperties(); 
     foreach (PropertyInfo pi in properties) 
     { 
      if (!ExistColumn(tableDescriptor, pi.Name)) continue; // field not found 
      if (dr[pi.Name] == DBNull.Value) continue; 

      if (pi.PropertyType.IsEnum) { } 
      else 
      { 
       switch (pi.PropertyType.Name) 
       { 
        case "DateTime": 
         object dateValue = null; 
         if (dr[pi.Name].GetType().Name == "String") 
          dateValue = F24Common.Utility.DateFromString(dr.GetString(dr.GetOrdinal(pi.Name))); 
         else 
          dateValue = dr.GetDateTime(dr.GetOrdinal(pi.Name)); 
         pi.SetValue(obj, dateValue, null); 
         break; 
        default: 
         pi.SetValue(obj, dr.GetValue(dr.GetOrdinal(pi.Name)), null); 
         break; 
       } 
      } 
     } 

    } 
    catch (Exception) 
    { 

    } 
} 

에 분명히 문제가 있습니다 이 코드는 너무 느립니다 (전체 처리에는 45-50 분 소요). 둘 이상의 CPU 코어 (쿼드 코어 CPU를 사용할 수 있음)를 동시에 사용하여 목록을 채울 수 있습니까?

+0

목록의 항목 순서가 중요합니까? 그렇지 않은 경우, 분명히해야 할 일은 각 스레드에 하나씩 4 개의 목록을 작성한 다음 끝에 결합하는 것입니다. 이렇게하면 모든 잠금이 방지됩니다. – Damon

+0

@Damon : 나는 이것을 사용하려고 생각했지만이 목록 다음에 생성 할 파일이 있으며 아직 파일을 시작하기 위해 4 개의 목록을 완료하는 방법을 모릅니다 (조금 읽어야합니다).) – Akrem

+0

당신은 그 장벽이 필요합니다. 스레드가 완료되면 장벽에 도달하여 임계 값에 도달 할 때까지 (즉 모든 스레드가 완료 될 때까지) 차단됩니다. 임계 값 5를 선택하고 장벽에 주 스레드 블록도 놓습니다. 노동자가 깨어 난 후 종료하면 주 스레드가 파일을 씁니다. 나는 C# 프로그래머가 아니지만 C#에는 [쉽게 사용할 수있는] 것 같습니다 (http://msdn.microsoft.com/de-de/library/system.threading.barrier.aspx). – Damon

답변

1

한눈에 병목 현상이 반사의 양에 있다고 생각합니다. Jon Skeets의 훌륭한 책인 Making Reflection fly article을 읽으라고 제안합니다. 그런 다음 obj 유형에 입력 된 해당 대리자를 캐시 할 수 있습니다.

그렇게하는 것이 안전하다고 생각하기 때문에 여러 스레드에서 DataReader에 액세스하는 것이 주저합니다.

+0

네, 그렇습니다. 이것은 모든 반사를 코딩하는 최악의 (가장 느린) 방법에 관한 것입니다. 모든 MethodInfo 인스턴스는 정적이며 ReadFromObject에 대한 메서드 호출 사이에 캐시 될 수 있습니다. 실제로이 원시 코드를 유지하면서 LINQ 공급자에게 사용하지 않으려 고하면 실제로 속도가 빨라집니다. – TomTom

+0

ok 나는 과 @TomTom :이 ReadFromObject를 변경하기 위해 Linq를 사용하는 방법을 설명하겠다. – Akrem

+0

SImple - 시작할 ReadFromObject 메소드가 없습니다. – TomTom