2016-10-18 16 views
0

私はDatatableに何百万ものレコードを持っています。私はParallel.Foreachを使って各レコードを取得しています。各レコードでメソッドAddAttendaceが呼び出されます。Cでの安全でない方法によるマルチスレッド

var AttCollection = from o in Employees 
        select o; 

Parallel.ForEach(AttCollection, ac => 
{ 
    AddAttendace(_ep.Get_V(ac.Key, true, null), ac.Value); 
}); 

そしてAddAttendace方法でデータベースからデータを取得するために使用するデータベースたっていることと呼ばれる他の複数の方法、私は、エンティティフレームワークを使用しています。

public bool AddAttendace(V_HR_EmployeePlacementDetailed emp, DateTime dt) 
{ 
    var empPos = _position.Get(emp.department_id, emp.position_id); 
    var empPosRoster = _rosterPosition.Get(emp.department_id, emp.position_id, dt); 

    var empPosLateArrival = empPos.late_arrival; 
    var empPosEarlyDeparture = empPos.early_departure; 

    if (empPosRoster != null) 
    { 
     empPosLateArrival = empPosRoster.late_arrival.HasValue ? empPosRoster.late_arrival.Value : empPosLateArrival; 
     empPosEarlyDeparture = empPosRoster.early_departure.HasValue ? empPosRoster.early_departure.Value : empPosEarlyDeparture; 
    } 

    var empLeaves = _lapp.GetAll(null, null, dt, dt, null, true, null, null, null, null); 

    var att = GetAll(dt, new List<long> { emp.employee_id }); 
    var obj = att.Count() > 0 ? att.First() : Get(); 
    var inRecords = _inOut.GetAll(obj.employee_attendance_id, true, null); 
    var outRecords = _inOut.GetAll(obj.employee_attendance_id, null, true); 

    obj.employee_id = emp.employee_id; 
    obj.date = dt; 
    obj.arrival_time = inRecords.Count() == 0 ? dt.TimeOfDay : obj.arrival_time; 
    obj.departure_time = inRecords.Count() > 0 ? dt.TimeOfDay : obj.departure_time; 

    dt.TimeOfDay - inRecords.First()[email protected] : obj.total_hours_worked; 

    if (obj.arrival_time.HasValue && empPosLateArrival.HasValue && obj.arrival_time > empPosLateArrival) 
     obj.late_arrival = obj.arrival_time - empPosLateArrival; 
    if (obj.early_departure.HasValue && empPosEarlyDeparture.HasValue && obj.departure_time < empPosEarlyDeparture) 
     obj.early_departure = empPosEarlyDeparture - obj.departure_time; 

     obj.present = true; 
     obj.leave = false; 
     obj.holiday = false; 
     obj.department_id = emp.department_id; 
     obj.position_id = emp.position_id; 

     var lapp = (from o in empLeaves 
        where o.employee_id == emp.employee_id 
        select o).FirstOrDefault(); 

    if (lapp != null && obj.present != true){ 
     obj.leave = true; 
     obj.leave_type_id = lapp.LeaveTypeId; 
     } 
    var v = _inOut.Get(); 
    if (att.Count() > 0){ 
     Update(); 
     v.attendance_id = obj.employee_attendance_id; 
     } 
    else{ 
      Insert(obj); 
      v.attendance_id = GetCurrentIdent(); 
     } 
     if (inRecords.Count() == 0){ 
      [email protected] = dt.TimeOfDay; 
      v.inout_type_id = 1; 
     } 
     else{ 
      [email protected] = dt.TimeOfDay; 
      v.inout_type_id = 2; 
       } 
      _inOut.Insert(v); 

      return false; 
      } 

AddAttendaceが実行完了するまでに2秒かかったと私はParallel.Foreachを使用持っている理由thatsのよう12000記録のためには、実行にとても時間がかかります。しかしAddAttendaceの内側と呼ばれる他の複数の方法が、私はそれぞれの方法

public V_HR_EmployeePlacementDetailed Get_V(long employeeID, bool? IsActivePlacement, bool? IsActive) 
{ 
    lock (locker) 
    { 
     var result = from o in entity.V_HR_EmployeePlacementDetailed 
        where o.employee_id == employeeID 
        && ((IsActive.HasValue && o.IsActive == IsActive) 
        || !IsActive.HasValue) 
        && ((IsActivePlacement.HasValue && o.IsActiveInPlacement == IsActivePlacement) 
        || !IsActivePlacement.HasValue) 
        orderby o.employee_placement_id descending 
        select o; 
     return result.FirstOrDefault(); 
    } 
} 

lockステートメントを使用しましたが、まだAddAttendace方法はいただきました間違った私のコードで、レコードごとに実行するために2秒を要し、スレッド安全ではありませんか? マルチスレッドの他の手法を使用する必要があります。

+0

EFコンテキストはスレッドセーフではありませんので、あなたは、各スレッドで別のコンテキストを持っていますか... – Dismissile

+0

には私が持っているdo'tませんが、私はしばらくのスレッドは、DBを使用しているのはこの理由のためにロックステートメントを使用していconext otherは待ち行列に入るはずです。 –

+1

実際に何が時間を費やしているかを見るためにプロファイラをつけてみましたか?最初の質問は、あなたのコードがDisk、CPU、Network boundのいずれであるかです。複数のスレッドでは、CPUバインドされたタスクのパフォーマンスが向上します。 https://msdn.microsoft.com/en-us/library/ms182372.aspx –

答えて

2

詳細については、これをプロファイルする必要があります。盲目的に問題を投げかけているスレッドは、単にトラブルの原因になりがちです。 Visual Studioには最新バージョンのプロファイラが含まれていますが、RedgateのANTSなどのツールを使用することもできます。そのことを理解できない場合は、問題を絞り込むために、コード全体に時間ログの呼び出しをスティックするだけです(下記参照)。問題の原因となっている正確な線が分かったら、最適化する価値があります。

public bool AddAttendace(V_HR_EmployeePlacementDetailed emp, DateTime dt) 
    { 
     var stopWatch = System.Diagnostics.Stopwatch.StartNew(); 

     var empPos = _position.Get(emp.department_id, emp.position_id); 
     System.Diagnostics.Debug.WriteLine("a {0}", stopWatch.ElapsedTicks); 
     var empPosRoster = _rosterPosition.Get(emp.department_id, emp.position_id, dt); 
     System.Diagnostics.Debug.WriteLine("b {0}", stopWatch.ElapsedTicks); 

     var empPosLateArrival = empPos.late_arrival; 
     var empPosEarlyDeparture = empPos.early_departure; 
     System.Diagnostics.Debug.WriteLine("c {0}", stopWatch.ElapsedTicks); 

     if (empPosRoster != null) 
     {     
      empPosLateArrival = empPosRoster.late_arrival.HasValue ? empPosRoster.late_arrival.Value : empPosLateArrival; 
      empPosEarlyDeparture = empPosRoster.early_departure.HasValue ? empPosRoster.early_departure.Value : empPosEarlyDeparture; 
      System.Diagnostics.Debug.WriteLine("d {0}", stopWatch.ElapsedTicks); 
     } 

     var empLeaves = _lapp.GetAll(null, null, dt, dt, null, true, null, null, null, null); 
     System.Diagnostics.Debug.WriteLine("e {0}", stopWatch.ElapsedTicks); 

     var att = GetAll(dt, new List<long> { emp.employee_id }); 
     System.Diagnostics.Debug.WriteLine("f {0}", stopWatch.ElapsedTicks); 
     var obj = att.Count() > 0 ? att.First() : Get(); 
     System.Diagnostics.Debug.WriteLine("g {0}", stopWatch.ElapsedTicks); 
     var inRecords = _inOut.GetAll(obj.employee_attendance_id, true, null); 
     System.Diagnostics.Debug.WriteLine("h {0}", stopWatch.ElapsedTicks); 
     var outRecords = _inOut.GetAll(obj.employee_attendance_id, null, true); 
     System.Diagnostics.Debug.WriteLine("i {0}", stopWatch.ElapsedTicks); 

     obj.employee_id = emp.employee_id; 
     obj.date = dt; 
     obj.arrival_time = inRecords.Count() == 0 ? dt.TimeOfDay : obj.arrival_time; 
     obj.departure_time = inRecords.Count() > 0 ? dt.TimeOfDay : obj.departure_time; 
     System.Diagnostics.Debug.WriteLine("j {0}", stopWatch.ElapsedTicks); 

     dt.TimeOfDay - inRecords.First()[email protected] : obj.total_hours_worked; 
     System.Diagnostics.Debug.WriteLine("k {0}", stopWatch.ElapsedTicks); 

     if (obj.arrival_time.HasValue && empPosLateArrival.HasValue && obj.arrival_time > empPosLateArrival) 
     { 
      obj.late_arrival = obj.arrival_time - empPosLateArrival; 
      System.Diagnostics.Debug.WriteLine("l {0}", stopWatch.ElapsedTicks); 
     } 
     if (obj.early_departure.HasValue && empPosEarlyDeparture.HasValue && obj.departure_time < empPosEarlyDeparture) 
     { 
      obj.early_departure = empPosEarlyDeparture - obj.departure_time; 
      System.Diagnostics.Debug.WriteLine("m {0}", stopWatch.ElapsedTicks); 
     } 

     obj.present = true; 
     obj.leave = false; 
     obj.holiday = false; 
     obj.department_id = emp.department_id; 
     obj.position_id = emp.position_id; 
     System.Diagnostics.Debug.WriteLine("n {0}", stopWatch.ElapsedTicks); 

     var lapp = (
      from o in empLeaves 
      where o.employee_id == emp.employee_id 
      select o).FirstOrDefault(); 
     System.Diagnostics.Debug.WriteLine("o {0}", stopWatch.ElapsedTicks); 

     if (lapp != null && obj.present != true) 
     { 
      obj.leave = true; 
      obj.leave_type_id = lapp.LeaveTypeId; 
      System.Diagnostics.Debug.WriteLine("p {0}", stopWatch.ElapsedTicks); 
     } 
     var v = _inOut.Get(); 
     System.Diagnostics.Debug.WriteLine("q {0}", stopWatch.ElapsedTicks); 
     if (att.Count() > 0) 
     { 
      Update(); 
      v.attendance_id = obj.employee_attendance_id; 
      System.Diagnostics.Debug.WriteLine("r {0}", stopWatch.ElapsedTicks); 
     } 
     else 
     { 
      Insert(obj); 
      v.attendance_id = GetCurrentIdent(); 
      System.Diagnostics.Debug.WriteLine("s {0}", stopWatch.ElapsedTicks); 
     } 
     if (inRecords.Count() == 0) 
     { 
      [email protected] = dt.TimeOfDay; 
      v.inout_type_id = 1; 
      System.Diagnostics.Debug.WriteLine("t {0}", stopWatch.ElapsedTicks); 
     } 
     else 
     { 
      [email protected] = dt.TimeOfDay; 
      v.inout_type_id = 2; 
      System.Diagnostics.Debug.WriteLine("u {0}", stopWatch.ElapsedTicks); 
     } 
     _inOut.Insert(v); 
     System.Diagnostics.Debug.WriteLine("v {0}", stopWatch.ElapsedTicks); 

     return false; 
    } 
関連する問題