私は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秒を要し、スレッド安全ではありませんか? マルチスレッドの他の手法を使用する必要があります。
EFコンテキストはスレッドセーフではありませんので、あなたは、各スレッドで別のコンテキストを持っていますか... – Dismissile
には私が持っているdo'tませんが、私はしばらくのスレッドは、DBを使用しているのはこの理由のためにロックステートメントを使用していconext otherは待ち行列に入るはずです。 –
実際に何が時間を費やしているかを見るためにプロファイラをつけてみましたか?最初の質問は、あなたのコードがDisk、CPU、Network boundのいずれであるかです。複数のスレッドでは、CPUバインドされたタスクのパフォーマンスが向上します。 https://msdn.microsoft.com/en-us/library/ms182372.aspx –