Вам лучше использовать блокирующую коллекцию, если вы просто не пытаетесь понять, как работает многопоточность.Это даст вам блокирующую коллекцию, поддерживаемую стеком:
ConcurrentStack<SomeType> MyStack = new ConcurrentStack<SomeType>();
BlockingCollection<SomeType> SharedStack = new BlockingCollection<SomeType>(MyStack)
После этого вы сможете получить к ней доступ в многопоточном режиме, и все блокировки будут выполнены для вас должным образом.См. здесь
. Вы можете использовать sharedStack, вызвав sharedStack.Take()
, который будет блокировать при получении, пока не будет что-то взять из стека.
Редактировать: Мне потребовалось некоторое время (и две попытки), но я решил вашу проблему, я думаю.
Рассмотрим пустой стек с 3 потоками, ожидающими события.
Вызов Add, стек имеет один объект, и один поток может проходить через событие.
Немедленно добавитьназывается снова.
Первый поток, проходящий сейчас, ожидает получения блокировки от Add.
Добавление добавляет второй объект в стек и пропускает другой поток через событие.
Теперь два объекта в стеке и 2 потока в событии, оба ожидают блокировки.
Первый поток Get теперь получает блокировку и всплывает.Еще видит один объект в стеке и вызывает CALLS SET.
Третий поток разрешен, хотя событие.
Второй поток Get теперь получает блокировку и выскакивает.Ничего не видит в стеке и не вызывает set.
НО.Слишком поздно.Третий поток уже пропущен, поэтому, когда второй поток снимает блокировку, третий поток пытается выскочить из пустого стека и выбросить.