Nulls в Producer - C#
Формулировка задачи:
Здравствуйте. Прошу помочь, потому как сам уже в душе не я... знаю как это разрешить
Застопорил на том, что потоки не завершаются после окончания. Т.е. один из рабочих потоков при этом очень быстро завершает самый последний блок и успевает пойти на следующий круг раньше, чем основной поток дождётся producer Join и положит туда nulls. В этом случае поток повиснет в куске
, т.к. не войдет в блок
Но я понятия не приложу как это реализовать, паттерн головного мозга.
Пользовался https://rsdn.org/article/dotnet/CSThreading1.xml
Листинг программы
- while (true)
- {
- Block block = null;
- try
- {
- lock (this.inputLockObj)
- {
- if (this.input.Count > 0)
- {
- block = this.input.Dequeue();
- if (block == null)
- return;
- }
- }
- this.readAdd.Set();
- if (block != null)
- {
- action.Act(block);
- this.EnqueueHandledBlock(block);
- }
- else
- {
- this.readGet.WaitOne();
- }
- }
- catch (ThreadAbortException e)
- {
- Console.WriteLine(e.Message);
- return;
- }
- catch (Exception e)
- {
- callback?.Invoke(e.Message);
- return;
- }
- }
Листинг программы
- this.readGet.WaitOne();
Листинг программы
- if (this.input.Count > 0)
- {
- block = this.input.Dequeue();
- if (block == null)
- return;
- }
Решение задачи: «Nulls в Producer»
textual
Листинг программы
- class ProducerConsumer
- {
- private Semaphore _workLimit;
- private ManualResetEvent _awaiter = new ManualResetEvent(true);
- private object _locker = new object();
- private Queue<Action> _work = new Queue<Action>();
- private int _threads;
- private int _abortsPending;
- public ProducerConsumer(int workLimit)
- {
- _workLimit = new Semaphore(workLimit, workLimit);
- }
- public void AddWorker()
- {
- var thread = new Thread(DoWork);
- thread.Start();
- lock (_locker)
- _threads++;
- }
- public void RemoveWorker()
- {
- lock (_locker)
- _abortsPending++;
- }
- public void Join()
- {
- _awaiter.WaitOne();
- lock (_locker)
- {
- _abortsPending += _threads - _abortsPending;
- Monitor.PulseAll(_locker);
- }
- }
- public void AddWork(Action workItem)
- {
- _workLimit.WaitOne();
- lock (_locker)
- {
- _work.Enqueue(workItem);
- Monitor.Pulse(_locker);
- _awaiter.Reset();
- }
- }
- private void DoWork()
- {
- while (true)
- {
- Action action = null;
- lock (_locker)
- {
- if (_work.Count == 0)
- _awaiter.Set();
- if (_abortsPending > 0)
- {
- _abortsPending--;
- _threads--;
- return;
- }
- while (!_work.Any())
- {
- Monitor.Wait(_locker);
- if (_abortsPending > 0)
- {
- _abortsPending--;
- _threads--;
- return;
- }
- }
- action = _work.Dequeue();
- }
- action();
- _workLimit.Release();
- }
- }
- }
- void Main()
- {
- var pc = new ProducerConsumer(1);
- pc.AddWorker();
- pc.AddWorker();
- pc.AddWorker();
- pc.AddWorker();
- pc.AddWorker();
- pc.AddWorker();
- pc.AddWorker();
- pc.AddWorker();
- pc.AddWorker();
- pc.AddWork(() => { Console.WriteLine("1"); Thread.Sleep(1000); });
- pc.AddWork(() => Console.WriteLine("2"));
- pc.AddWork(() => Console.WriteLine("3"));
- pc.AddWork(() => { Console.WriteLine("4"); Thread.Sleep(1000); });
- Console.WriteLine("Join");
- pc.Join();
- Console.WriteLine("End");
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д