Вы разрешаете запускать три потока одновременно:
new Semaphore(3, 3);
Значит, ваш Semaphore
не очень вам помогает, потому что вы на самом деле не блокируете. Таким образом, у вас все еще есть проблема, когда, например, вы можете оставить одно сообщение в списке, но все 3 потока оценивают messagesList.Count > 0
как true
. Один из этих потоков сначала удалит элемент из списка, что приведет к тому, что другие два сгенерируют исключение.
Есть лучшие способы сделать это. Для списков мне нравится использовать ReaderWriterLockSlim
, который имеет блокировки чтения и записи. Он позволяет читать все потоки, но блокирует всех, как только вы блокируете запись. Вот пример того, как использовать это в документации.