public void ChangeNumberThreads(int countThreads) { lock (locker) { if (countThreads == ThreadsCount) { return; } ThreadsCount = countThreads; if (threads != null) { foreach (var thread in threads) { thread?.Abort(); } while (!FreeThreads.IsEmpty) { FreeThreads.TryDequeue(out _); } } if (countThreads > 0) { threads = new ThreadUnit[ThreadsCount]; for (var i = 0; i < ThreadsCount; i++) { threads[i] = new ThreadUnit($"Thread #{i}", i); FreeThreads.Enqueue(threads[i]); } } else { threads = null; } } }
public void Process(object o) { if (threads == null) { return; } if (Interlocked.CompareExchange(ref _lock, 1, 0) == 1) { return; } if (ProcessWorking) { DebugWindow.LogMsg($"WTF {_objectInitWork.GetType()}"); } _objectInitWork = o; ProcessWorking = true; spinWait.Reset(); while (Jobs.TryDequeue(out var j)) { processJobs.Enqueue(j); } if (ThreadsCount > 1) { while (processJobs.Count > 0) { if (!FreeThreads.IsEmpty) { FreeThreads.TryDequeue(out var freeThread); var job = processJobs.Dequeue(); if (!freeThread.AddJob(job)) { processJobs.Enqueue(job); } else { if (freeThread.Free) { FreeThreads.Enqueue(freeThread); } } } else { spinWait.SpinOnce(); var allThreadsBusy = true; for (int i = 0; i < threads.Length; i++) { var th = threads[i]; if (th.Free) { allThreadsBusy = false; FreeThreads.Enqueue(th); } } if (allThreadsBusy) { for (int i = 0; i < threads.Length; i++) { var th = threads[i]; var thWorkingTime = th.WorkingTime; if (thWorkingTime > CriticalWorkTimeMs) { DebugWindow.LogMsg( $"Repair thread #{th.Number} with Job1: {th.Job.Name} (C: {th.Job.IsCompleted} F: {th.Job.IsFailed}) && Job2:{th.SecondJob.Name} (C: {th.SecondJob.IsCompleted} F: {th.SecondJob.IsFailed}) Time: {thWorkingTime} > {thWorkingTime >= CriticalWorkTimeMs}", 5); th.Abort(); BrokenThreads.Add(th); var newThread = new ThreadUnit($"Repair critical time {th.Number}", th.Number); threads[th.Number] = newThread; FreeThreads.Enqueue(newThread); Thread.Sleep(5); FailedThreadsCount++; break; } } } } } } else { var threadUnit = threads[0]; while (processJobs.Count > 0) { if (threadUnit.Free) { var job = processJobs.Dequeue(); threadUnit.AddJob(job); } else { spinWait.SpinOnce(); var threadUnitWorkingTime = threadUnit.WorkingTime; if (threadUnitWorkingTime > CriticalWorkTimeMs) { DebugWindow.LogMsg( $"Repair thread #{threadUnit.Number} withreadUnit Job1: {threadUnit.Job.Name} (C: {threadUnit.Job.IsCompleted} F: {threadUnit.Job.IsFailed}) && Job2:{threadUnit.SecondJob.Name} (C: {threadUnit.SecondJob.IsCompleted} F: {threadUnit.SecondJob.IsFailed}) Time: {threadUnitWorkingTime} > {threadUnitWorkingTime >= CriticalWorkTimeMs}", 5); threadUnit.Abort(); BrokenThreads.Add(threadUnit); threadUnit = new ThreadUnit($"Repair critical time {threadUnit.Number}", threadUnit.Number); Thread.Sleep(5); FailedThreadsCount++; } } } } if (BrokenThreads.Count > 0) { var criticalWorkTimeMs = CriticalWorkTimeMs * 2; for (var index = 0; index < BrokenThreads.Count; index++) { var brokenThread = BrokenThreads[index]; if (brokenThread == null) { continue; } if (brokenThread.WorkingTime > criticalWorkTimeMs) { brokenThread.ForceAbort(); BrokenThreads[index] = null; } } if (BrokenThreads.AllF(x => x == null)) { BrokenThreads.Clear(); } } Interlocked.CompareExchange(ref _lock, 0, 1); ProcessWorking = false; }