Nulls в Producer - C#

Узнай цену своей работы

Формулировка задачи:

Здравствуйте. Прошу помочь, потому как сам уже в душе не я... знаю как это разрешить
Листинг программы
  1. while (true)
  2. {
  3. Block block = null;
  4. try
  5. {
  6. lock (this.inputLockObj)
  7. {
  8. if (this.input.Count > 0)
  9. {
  10. block = this.input.Dequeue();
  11. if (block == null)
  12. return;
  13. }
  14. }
  15. this.readAdd.Set();
  16. if (block != null)
  17. {
  18. action.Act(block);
  19. this.EnqueueHandledBlock(block);
  20. }
  21. else
  22. {
  23. this.readGet.WaitOne();
  24. }
  25. }
  26. catch (ThreadAbortException e)
  27. {
  28. Console.WriteLine(e.Message);
  29. return;
  30. }
  31. catch (Exception e)
  32. {
  33. callback?.Invoke(e.Message);
  34. return;
  35. }
  36. }
Застопорил на том, что потоки не завершаются после окончания. Т.е. один из рабочих потоков при этом очень быстро завершает самый последний блок и успевает пойти на следующий круг раньше, чем основной поток дождётся producer Join и положит туда nulls. В этом случае поток повиснет в куске
Листинг программы
  1. this.readGet.WaitOne();
, т.к. не войдет в блок
Листинг программы
  1. if (this.input.Count > 0)
  2. {
  3. block = this.input.Dequeue();
  4. if (block == null)
  5. return;
  6. }
Но я понятия не приложу как это реализовать, паттерн головного мозга. Пользовался https://rsdn.org/article/dotnet/CSThreading1.xml

Решение задачи: «Nulls в Producer»

textual
Листинг программы
  1. class ProducerConsumer
  2. {
  3.     private Semaphore _workLimit;
  4.     private ManualResetEvent _awaiter = new ManualResetEvent(true);
  5.     private object _locker = new object();
  6.     private Queue<Action> _work = new Queue<Action>();
  7.     private int _threads;
  8.     private int _abortsPending;
  9.    
  10.     public ProducerConsumer(int workLimit)
  11.     {
  12.         _workLimit = new Semaphore(workLimit, workLimit);
  13.     }
  14.    
  15.     public void AddWorker()
  16.     {
  17.         var thread = new Thread(DoWork);
  18.         thread.Start();
  19.        
  20.         lock (_locker)
  21.             _threads++;
  22.     }
  23.    
  24.     public void RemoveWorker()
  25.     {
  26.         lock (_locker)
  27.             _abortsPending++;
  28.     }
  29.    
  30.     public void Join()
  31.     {      
  32.         _awaiter.WaitOne();
  33.  
  34.         lock (_locker)
  35.         {
  36.             _abortsPending += _threads - _abortsPending;
  37.             Monitor.PulseAll(_locker);
  38.         }
  39.     }
  40.  
  41.     public void AddWork(Action workItem)
  42.     {
  43.         _workLimit.WaitOne();
  44.        
  45.         lock (_locker)
  46.         {
  47.             _work.Enqueue(workItem);
  48.             Monitor.Pulse(_locker);
  49.             _awaiter.Reset();
  50.         }
  51.     }
  52.    
  53.     private void DoWork()
  54.     {
  55.         while (true)
  56.         {
  57.             Action action = null;
  58.  
  59.             lock (_locker)
  60.             {
  61.                 if (_work.Count == 0)
  62.                     _awaiter.Set();
  63.                    
  64.                 if (_abortsPending > 0)
  65.                 {
  66.                     _abortsPending--;
  67.                     _threads--;
  68.                     return;
  69.                 }
  70.  
  71.                 while (!_work.Any())
  72.                 {
  73.                     Monitor.Wait(_locker);
  74.  
  75.                     if (_abortsPending > 0)
  76.                     {
  77.                         _abortsPending--;
  78.                         _threads--;
  79.                         return;
  80.                     }
  81.                 }
  82.  
  83.                 action = _work.Dequeue();
  84.             }
  85.  
  86.             action();
  87.            
  88.             _workLimit.Release();
  89.         }
  90.     }
  91. }
  92.  
  93. void Main()
  94. {
  95.     var pc = new ProducerConsumer(1);
  96.    
  97.     pc.AddWorker();
  98.     pc.AddWorker();
  99.     pc.AddWorker();
  100.     pc.AddWorker();
  101.     pc.AddWorker();
  102.     pc.AddWorker();
  103.     pc.AddWorker();
  104.     pc.AddWorker();
  105.     pc.AddWorker();
  106.  
  107.     pc.AddWork(() => { Console.WriteLine("1"); Thread.Sleep(1000); });
  108.     pc.AddWork(() => Console.WriteLine("2"));
  109.     pc.AddWork(() => Console.WriteLine("3"));
  110.     pc.AddWork(() => { Console.WriteLine("4"); Thread.Sleep(1000); });
  111.    
  112.     Console.WriteLine("Join");
  113.     pc.Join();
  114.     Console.WriteLine("End");
  115. }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

5   голосов , оценка 4 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы