Changeset 6725 for branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/TaskManager.cs
- Timestamp:
- 09/08/11 16:38:28 (13 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.Hive-3.4/sources/HeuristicLab.Clients.Hive.Slave/3.3/Manager/TaskManager.cs
r6721 r6725 30 30 31 31 /// <summary> 32 /// Holds a list of slave jobs and manages access to this list.33 /// Forwards events from Slave Job and forwards commands to SlaveJob.32 /// Holds a list of slave tasks and manages access to this list. 33 /// Forwards events from SlaveTask and forwards commands to SlaveTask. 34 34 /// </summary> 35 public class JobManager {36 private static ReaderWriterLockSlim slave JobsLocker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);37 private Dictionary<Guid, Slave Job> slaveJobs;35 public class TaskManager { 36 private static ReaderWriterLockSlim slaveTasksLocker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); 37 private Dictionary<Guid, SlaveTask> slaveTasks; 38 38 private ILog log; 39 39 private PluginManager pluginManager; 40 40 41 public int JobCount {41 public int TaskCount { 42 42 get { 43 slave JobsLocker.EnterReadLock();43 slaveTasksLocker.EnterReadLock(); 44 44 try { 45 return slave Jobs.Count;46 } 47 finally { slave JobsLocker.ExitReadLock(); }48 } 49 } 50 51 public Guid[] JobIds {45 return slaveTasks.Count; 46 } 47 finally { slaveTasksLocker.ExitReadLock(); } 48 } 49 } 50 51 public Guid[] TaskIds { 52 52 get { 53 slave JobsLocker.EnterReadLock();53 slaveTasksLocker.EnterReadLock(); 54 54 try { 55 return slave Jobs.Keys.ToArray();56 } 57 finally { slave JobsLocker.ExitReadLock(); }58 } 59 } 60 61 public JobManager(PluginManager pluginCache, ILog log) {55 return slaveTasks.Keys.ToArray(); 56 } 57 finally { slaveTasksLocker.ExitReadLock(); } 58 } 59 } 60 61 public TaskManager(PluginManager pluginCache, ILog log) { 62 62 this.pluginManager = pluginCache; 63 63 this.log = log; 64 this.slave Jobs = new Dictionary<Guid, SlaveJob>();64 this.slaveTasks = new Dictionary<Guid, SlaveTask>(); 65 65 } 66 66 67 67 #region Task Control methods 68 public void Start JobAsync(Task job, TaskData jobData) {69 Slave Job slaveJob= null;70 slave JobsLocker.EnterUpgradeableReadLock();71 try { 72 if (slave Jobs.ContainsKey(job.Id)) {68 public void StartTaskAsync(Task task, TaskData taskData) { 69 SlaveTask slaveTask = null; 70 slaveTasksLocker.EnterUpgradeableReadLock(); 71 try { 72 if (slaveTasks.ContainsKey(task.Id)) { 73 73 SlaveStatusInfo.IncrementExceptionOccured(); 74 throw new JobAlreadyRunningException(job.Id);74 throw new TaskAlreadyRunningException(task.Id); 75 75 } else { 76 slave Job = new SlaveJob(pluginManager, job.CoresNeeded, log);77 AddSlave Job(job, slaveJob);78 SlaveStatusInfo.Increment JobsFetched();79 } 80 } 81 finally { slave JobsLocker.ExitUpgradeableReadLock(); }82 83 if (slave Job!= null) {76 slaveTask = new SlaveTask(pluginManager, task.CoresNeeded, log); 77 AddSlaveTask(task, slaveTask); 78 SlaveStatusInfo.IncrementTasksFetched(); 79 } 80 } 81 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 82 83 if (slaveTask != null) { 84 84 try { 85 slave Job.StartJobAsync(job, jobData);85 slaveTask.StartJobAsync(task, taskData); 86 86 } 87 87 catch (Exception) { 88 RemoveSlave Job(job.Id, slaveJob); // clean up and rethrow89 slave Job.DisposeAppDomain();88 RemoveSlaveTask(task.Id, slaveTask); // clean up and rethrow 89 slaveTask.DisposeAppDomain(); 90 90 throw; 91 91 } … … 93 93 } 94 94 95 public void Pause JobAsync(Guid jobId) {96 slave JobsLocker.EnterUpgradeableReadLock();97 try { 98 if (!slave Jobs.ContainsKey(jobId)) throw new JobNotRunningException(jobId);99 Slave Job slaveJob = slaveJobs[jobId];100 slave Job.PauseJob();101 } 102 finally { slave JobsLocker.ExitUpgradeableReadLock(); }103 } 104 105 public void Stop JobAsync(Guid jobId) {106 slave JobsLocker.EnterUpgradeableReadLock();107 try { 108 if (!slave Jobs.ContainsKey(jobId)) throw new JobNotRunningException(jobId);109 Slave Job slaveJob = slaveJobs[jobId];110 slave Job.StopJob();111 } 112 finally { slave JobsLocker.ExitUpgradeableReadLock(); }113 } 114 115 public void Abort Job(Guid jobId) {116 Slave Job slaveJob= null;117 slave JobsLocker.EnterUpgradeableReadLock();118 try { 119 if (!slave Jobs.ContainsKey(jobId)) throw new JobNotRunningException(jobId);120 slave Job = slaveJobs[jobId];121 if (!slave Job.IsPrepared) throw new AppDomainNotCreatedException();122 RemoveSlave Job(jobId, slaveJob);123 } 124 finally { slave JobsLocker.ExitUpgradeableReadLock(); }125 slave Job.DisposeAppDomain();126 SlaveStatusInfo.Increment JobsAborted();127 On JobAborted(slaveJob);128 } 129 130 public void PauseAll JobsAsync() {131 slave JobsLocker.EnterUpgradeableReadLock();132 try { 133 foreach (var slave Job in slaveJobs.Values) {134 slave Job.PauseJob();135 } 136 } 137 finally { slave JobsLocker.ExitUpgradeableReadLock(); }138 } 139 140 public void StopAll JobsAsync() {141 slave JobsLocker.EnterUpgradeableReadLock();142 try { 143 foreach (var slave Job in slaveJobs.Values) {144 slave Job.StopJob();145 } 146 } 147 finally { slave JobsLocker.ExitUpgradeableReadLock(); }148 } 149 150 public void AbortAll Jobs() {151 slave JobsLocker.EnterUpgradeableReadLock();152 try { 153 foreach (var slave Job in slaveJobs.Values.ToArray()) {154 Abort Job(slaveJob.JobId);155 } 156 } 157 finally { slave JobsLocker.ExitUpgradeableReadLock(); }95 public void PauseTaskAsync(Guid taskId) { 96 slaveTasksLocker.EnterUpgradeableReadLock(); 97 try { 98 if (!slaveTasks.ContainsKey(taskId)) throw new TaskNotRunningException(taskId); 99 SlaveTask slaveTask = slaveTasks[taskId]; 100 slaveTask.PauseTask(); 101 } 102 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 103 } 104 105 public void StopTaskAsync(Guid taskId) { 106 slaveTasksLocker.EnterUpgradeableReadLock(); 107 try { 108 if (!slaveTasks.ContainsKey(taskId)) throw new TaskNotRunningException(taskId); 109 SlaveTask slaveTask = slaveTasks[taskId]; 110 slaveTask.StopTask(); 111 } 112 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 113 } 114 115 public void AbortTask(Guid taskId) { 116 SlaveTask slaveTask = null; 117 slaveTasksLocker.EnterUpgradeableReadLock(); 118 try { 119 if (!slaveTasks.ContainsKey(taskId)) throw new TaskNotRunningException(taskId); 120 slaveTask = slaveTasks[taskId]; 121 if (!slaveTask.IsPrepared) throw new AppDomainNotCreatedException(); 122 RemoveSlaveTask(taskId, slaveTask); 123 } 124 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 125 slaveTask.DisposeAppDomain(); 126 SlaveStatusInfo.IncrementTasksAborted(); 127 OnTaskAborted(slaveTask); 128 } 129 130 public void PauseAllTasksAsync() { 131 slaveTasksLocker.EnterUpgradeableReadLock(); 132 try { 133 foreach (var slaveTask in slaveTasks.Values) { 134 slaveTask.PauseTask(); 135 } 136 } 137 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 138 } 139 140 public void StopAllTasksAsync() { 141 slaveTasksLocker.EnterUpgradeableReadLock(); 142 try { 143 foreach (var slaveTask in slaveTasks.Values) { 144 slaveTask.StopTask(); 145 } 146 } 147 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 148 } 149 150 public void AbortAllTasks() { 151 slaveTasksLocker.EnterUpgradeableReadLock(); 152 try { 153 foreach (var slaveTask in slaveTasks.Values.ToArray()) { 154 AbortTask(slaveTask.TaskId); 155 } 156 } 157 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 158 158 } 159 159 #endregion 160 160 161 #region Add/Remove Slave Job162 private void AddSlave Job(Task job, SlaveJob slaveJob) {163 slave JobsLocker.EnterWriteLock();164 try { 165 slave Jobs.Add(job.Id, slaveJob);166 RegisterSlave JobEvents(slaveJob);167 } 168 finally { slave JobsLocker.ExitWriteLock(); }169 } 170 171 private void RemoveSlave Job(Guid jobId, SlaveJob slaveJob) {172 slave JobsLocker.EnterWriteLock();173 try { 174 slave Jobs.Remove(jobId);175 DeregisterSlave JobEvents(slaveJob);176 } 177 finally { slave JobsLocker.ExitWriteLock(); }161 #region Add/Remove SlaveTask 162 private void AddSlaveTask(Task task, SlaveTask slaveTask) { 163 slaveTasksLocker.EnterWriteLock(); 164 try { 165 slaveTasks.Add(task.Id, slaveTask); 166 RegisterSlaveTaskEvents(slaveTask); 167 } 168 finally { slaveTasksLocker.ExitWriteLock(); } 169 } 170 171 private void RemoveSlaveTask(Guid taskId, SlaveTask slaveTask) { 172 slaveTasksLocker.EnterWriteLock(); 173 try { 174 slaveTasks.Remove(taskId); 175 DeregisterSlaveTaskEvents(slaveTask); 176 } 177 finally { slaveTasksLocker.ExitWriteLock(); } 178 178 } 179 179 #endregion 180 180 181 #region Slave JobEvents182 private void RegisterSlave JobEvents(SlaveJob slaveJob) {183 slave Job.JobStarted += new EventHandler<EventArgs<Guid>>(slaveJob_JobStarted);184 slave Job.JobPaused += new EventHandler<EventArgs<Guid>>(slaveJob_JobPaused);185 slave Job.JobStopped += new EventHandler<EventArgs<Guid>>(slaveJob_JobStopped);186 slave Job.JobFailed += new EventHandler<EventArgs<Guid, Exception>>(slaveJob_JobFailed);187 slave Job.ExceptionOccured += new EventHandler<EventArgs<Guid, Exception>>(slaveJob_ExceptionOccured);188 } 189 190 private void DeregisterSlave JobEvents(SlaveJob slaveJob) {191 slave Job.JobStarted -= new EventHandler<EventArgs<Guid>>(slaveJob_JobStarted);192 slave Job.JobPaused -= new EventHandler<EventArgs<Guid>>(slaveJob_JobPaused);193 slave Job.JobStopped -= new EventHandler<EventArgs<Guid>>(slaveJob_JobStopped);194 slave Job.JobFailed -= new EventHandler<EventArgs<Guid, Exception>>(slaveJob_JobFailed);195 slave Job.ExceptionOccured -= new EventHandler<EventArgs<Guid, Exception>>(slaveJob_ExceptionOccured);196 } 197 198 private void slave Job_JobStarted(object sender, EventArgs<Guid> e) {199 Slave Job slaveJob;200 slave JobsLocker.EnterUpgradeableReadLock();201 try { 202 slave Job = slaveJobs[e.Value];203 } 204 finally { slave JobsLocker.ExitUpgradeableReadLock(); }205 206 SlaveStatusInfo.Increment JobsStarted();207 On JobStarted(slaveJob);208 } 209 210 private void slave Job_JobPaused(object sender, EventArgs<Guid> e) {211 Slave Job slaveJob;212 slave JobsLocker.EnterUpgradeableReadLock();213 try { 214 slave Job = slaveJobs[e.Value];215 RemoveSlave Job(e.Value, slaveJob);216 } 217 finally { slave JobsLocker.ExitUpgradeableReadLock(); }218 219 TaskData jobData = null;220 try { 221 jobData = slaveJob.GetJobData();222 if ( jobData == null) throw new SerializationException();223 SlaveStatusInfo.Increment JobsFinished();224 On JobPaused(slaveJob, jobData);181 #region SlaveTask Events 182 private void RegisterSlaveTaskEvents(SlaveTask slaveTask) { 183 slaveTask.TaskStarted += new EventHandler<EventArgs<Guid>>(slaveTask_TaskStarted); 184 slaveTask.TaskPaused += new EventHandler<EventArgs<Guid>>(slaveTask_TaskPaused); 185 slaveTask.TaskStopped += new EventHandler<EventArgs<Guid>>(slaveTask_TaskStopped); 186 slaveTask.TaskFailed += new EventHandler<EventArgs<Guid, Exception>>(slaveTask_TaskFailed); 187 slaveTask.ExceptionOccured += new EventHandler<EventArgs<Guid, Exception>>(slaveTask_ExceptionOccured); 188 } 189 190 private void DeregisterSlaveTaskEvents(SlaveTask slaveTask) { 191 slaveTask.TaskStarted -= new EventHandler<EventArgs<Guid>>(slaveTask_TaskStarted); 192 slaveTask.TaskPaused -= new EventHandler<EventArgs<Guid>>(slaveTask_TaskPaused); 193 slaveTask.TaskStopped -= new EventHandler<EventArgs<Guid>>(slaveTask_TaskStopped); 194 slaveTask.TaskFailed -= new EventHandler<EventArgs<Guid, Exception>>(slaveTask_TaskFailed); 195 slaveTask.ExceptionOccured -= new EventHandler<EventArgs<Guid, Exception>>(slaveTask_ExceptionOccured); 196 } 197 198 private void slaveTask_TaskStarted(object sender, EventArgs<Guid> e) { 199 SlaveTask slaveTask; 200 slaveTasksLocker.EnterUpgradeableReadLock(); 201 try { 202 slaveTask = slaveTasks[e.Value]; 203 } 204 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 205 206 SlaveStatusInfo.IncrementTasksStarted(); 207 OnTaskStarted(slaveTask); 208 } 209 210 private void slaveTask_TaskPaused(object sender, EventArgs<Guid> e) { 211 SlaveTask slaveTask; 212 slaveTasksLocker.EnterUpgradeableReadLock(); 213 try { 214 slaveTask = slaveTasks[e.Value]; 215 RemoveSlaveTask(e.Value, slaveTask); 216 } 217 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 218 219 TaskData taskData = null; 220 try { 221 taskData = slaveTask.GetTaskData(); 222 if (taskData == null) throw new SerializationException(); 223 SlaveStatusInfo.IncrementTasksFinished(); 224 OnTaskPaused(slaveTask, taskData); 225 225 } 226 226 catch (Exception ex) { 227 RemoveSlave Job(e.Value, slaveJob);228 SlaveStatusInfo.Increment JobsFailed();229 On JobFailed(slaveJob, jobData, ex);230 } 231 } 232 233 private void slave Job_JobStopped(object sender, EventArgs<Guid> e) {234 Slave Job slaveJob;235 slave JobsLocker.EnterUpgradeableReadLock();236 try { 237 slave Job = slaveJobs[e.Value];238 RemoveSlave Job(e.Value, slaveJob);239 } 240 finally { slave JobsLocker.ExitUpgradeableReadLock(); }241 242 TaskData jobData = null;243 try { 244 jobData = slaveJob.GetJobData();245 if ( jobData == null) throw new SerializationException();246 SlaveStatusInfo.Increment JobsFinished();247 On JobStopped(slaveJob, jobData);227 RemoveSlaveTask(e.Value, slaveTask); 228 SlaveStatusInfo.IncrementTasksFailed(); 229 OnTaskFailed(slaveTask, taskData, ex); 230 } 231 } 232 233 private void slaveTask_TaskStopped(object sender, EventArgs<Guid> e) { 234 SlaveTask slaveTask; 235 slaveTasksLocker.EnterUpgradeableReadLock(); 236 try { 237 slaveTask = slaveTasks[e.Value]; 238 RemoveSlaveTask(e.Value, slaveTask); 239 } 240 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 241 242 TaskData taskData = null; 243 try { 244 taskData = slaveTask.GetTaskData(); 245 if (taskData == null) throw new SerializationException(); 246 SlaveStatusInfo.IncrementTasksFinished(); 247 OnTaskStopped(slaveTask, taskData); 248 248 } 249 249 catch (Exception ex) { 250 RemoveSlave Job(e.Value, slaveJob);251 SlaveStatusInfo.Increment JobsFailed();252 On JobFailed(slaveJob, jobData, ex);253 } 254 } 255 256 private void slave Job_JobFailed(object sender, EventArgs<Guid, Exception> e) {257 Slave Job slaveJob;258 slave JobsLocker.EnterUpgradeableReadLock();259 try { 260 slave Job = slaveJobs[e.Value];261 RemoveSlave Job(e.Value, slaveJob);262 } 263 finally { slave JobsLocker.ExitUpgradeableReadLock(); }264 265 TaskData jobData = null;266 try { 267 jobData = slaveJob.GetJobData();268 if ( jobData == null) throw new SerializationException();269 } 270 catch { /* jobData will be null */ }271 SlaveStatusInfo.Increment JobsFailed();272 On JobFailed(slaveJob, jobData, e.Value2);273 } 274 275 private void slave Job_ExceptionOccured(object sender, EventArgs<Guid, Exception> e) {276 Slave Job slaveJob;277 slave JobsLocker.EnterUpgradeableReadLock();278 try { 279 slave Job = slaveJobs[e.Value];280 RemoveSlave Job(e.Value, slaveJob);281 } 282 finally { slave JobsLocker.ExitUpgradeableReadLock(); }250 RemoveSlaveTask(e.Value, slaveTask); 251 SlaveStatusInfo.IncrementTasksFailed(); 252 OnTaskFailed(slaveTask, taskData, ex); 253 } 254 } 255 256 private void slaveTask_TaskFailed(object sender, EventArgs<Guid, Exception> e) { 257 SlaveTask slaveTask; 258 slaveTasksLocker.EnterUpgradeableReadLock(); 259 try { 260 slaveTask = slaveTasks[e.Value]; 261 RemoveSlaveTask(e.Value, slaveTask); 262 } 263 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 264 265 TaskData taskData = null; 266 try { 267 taskData = slaveTask.GetTaskData(); 268 if (taskData == null) throw new SerializationException(); 269 } 270 catch { /* taskData will be null */ } 271 SlaveStatusInfo.IncrementTasksFailed(); 272 OnTaskFailed(slaveTask, taskData, e.Value2); 273 } 274 275 private void slaveTask_ExceptionOccured(object sender, EventArgs<Guid, Exception> e) { 276 SlaveTask slaveTask; 277 slaveTasksLocker.EnterUpgradeableReadLock(); 278 try { 279 slaveTask = slaveTasks[e.Value]; 280 RemoveSlaveTask(e.Value, slaveTask); 281 } 282 finally { slaveTasksLocker.ExitUpgradeableReadLock(); } 283 283 284 284 SlaveStatusInfo.IncrementExceptionOccured(); 285 OnExceptionOccured(slave Job, e.Value2);285 OnExceptionOccured(slaveTask, e.Value2); 286 286 } 287 287 #endregion 288 288 289 289 #region EventHandler 290 public event EventHandler<EventArgs<Slave Job>> JobStarted;291 private void On JobStarted(SlaveJob slaveJob) {292 var handler = JobStarted;293 if (handler != null) handler(this, new EventArgs<Slave Job>(slaveJob));294 } 295 296 public event EventHandler<EventArgs<Slave Job, TaskData>> JobStopped;297 private void On JobStopped(SlaveJob slaveJob, TaskData jobData) {298 var handler = JobStopped;299 if (handler != null) handler(this, new EventArgs<Slave Job, TaskData>(slaveJob, jobData));300 } 301 302 public event EventHandler<EventArgs<Slave Job, TaskData>> JobPaused;303 private void On JobPaused(SlaveJob slaveJob, TaskData jobData) {304 var handler = JobPaused;305 if (handler != null) handler(this, new EventArgs<Slave Job, TaskData>(slaveJob, jobData));306 } 307 308 public event EventHandler<EventArgs<Tuple<Slave Job, TaskData, Exception>>> JobFailed;309 private void On JobFailed(SlaveJob slaveJob, TaskData jobData, Exception exception) {310 var handler = JobFailed;311 if (handler != null) handler(this, new EventArgs<Tuple<Slave Job, TaskData, Exception>>(new Tuple<SlaveJob, TaskData, Exception>(slaveJob, jobData, exception)));312 } 313 314 public event EventHandler<EventArgs<Slave Job, Exception>> ExceptionOccured;315 private void OnExceptionOccured(Slave Job slaveJob, Exception exception) {290 public event EventHandler<EventArgs<SlaveTask>> TaskStarted; 291 private void OnTaskStarted(SlaveTask slaveTask) { 292 var handler = TaskStarted; 293 if (handler != null) handler(this, new EventArgs<SlaveTask>(slaveTask)); 294 } 295 296 public event EventHandler<EventArgs<SlaveTask, TaskData>> TaskStopped; 297 private void OnTaskStopped(SlaveTask slaveTask, TaskData taskData) { 298 var handler = TaskStopped; 299 if (handler != null) handler(this, new EventArgs<SlaveTask, TaskData>(slaveTask, taskData)); 300 } 301 302 public event EventHandler<EventArgs<SlaveTask, TaskData>> TaskPaused; 303 private void OnTaskPaused(SlaveTask slaveTask, TaskData taskData) { 304 var handler = TaskPaused; 305 if (handler != null) handler(this, new EventArgs<SlaveTask, TaskData>(slaveTask, taskData)); 306 } 307 308 public event EventHandler<EventArgs<Tuple<SlaveTask, TaskData, Exception>>> TaskFailed; 309 private void OnTaskFailed(SlaveTask slaveTask, TaskData taskData, Exception exception) { 310 var handler = TaskFailed; 311 if (handler != null) handler(this, new EventArgs<Tuple<SlaveTask, TaskData, Exception>>(new Tuple<SlaveTask, TaskData, Exception>(slaveTask, taskData, exception))); 312 } 313 314 public event EventHandler<EventArgs<SlaveTask, Exception>> ExceptionOccured; 315 private void OnExceptionOccured(SlaveTask slaveTask, Exception exception) { 316 316 var handler = ExceptionOccured; 317 if (handler != null) handler(this, new EventArgs<Slave Job, Exception>(slaveJob, exception));318 } 319 320 public event EventHandler<EventArgs<Slave Job>> JobAborted;321 private void On JobAborted(SlaveJob slaveJob) {322 var handler = JobAborted;323 if (handler != null) handler(this, new EventArgs<Slave Job>(slaveJob));317 if (handler != null) handler(this, new EventArgs<SlaveTask, Exception>(slaveTask, exception)); 318 } 319 320 public event EventHandler<EventArgs<SlaveTask>> TaskAborted; 321 private void OnTaskAborted(SlaveTask slaveTask) { 322 var handler = TaskAborted; 323 if (handler != null) handler(this, new EventArgs<SlaveTask>(slaveTask)); 324 324 } 325 325 #endregion 326 326 327 327 public Dictionary<Guid, TimeSpan> GetExecutionTimes() { 328 slave JobsLocker.EnterReadLock();329 try { 330 return slave Jobs.ToDictionary(x => x.Key, x => x.Value.ExecutionTime);331 } 332 finally { slave JobsLocker.ExitReadLock(); }328 slaveTasksLocker.EnterReadLock(); 329 try { 330 return slaveTasks.ToDictionary(x => x.Key, x => x.Value.ExecutionTime); 331 } 332 finally { slaveTasksLocker.ExitReadLock(); } 333 333 } 334 334 }
Note: See TracChangeset
for help on using the changeset viewer.