Вызовы mSemaphore.Wait()
и mSemaphore.Release()
внутри вашего for
цикла. После каждой итерации цикла каждая задача освобождает семафор, а затем пытается получить его снова.
Учитывая это, ничто не мешает задаче 0, 1 или 2 освободить семафор в конце циклаи задача3 от его приобретения. Выпустившая его задача вернется к началу цикла и снова сядет на mSemaphore.Wait()
, ожидая, пока другая задача освободит семафор.
Все ваши задачи выполняются одновременно (кромеиз очень маленькой начальной задержки, потенциально), и все они имеют равный приоритет (SemaphoreSlim не гарантирует порядок, в котором вещи, ожидающие семафор, приобретают его - это, по сути, случайное, какая задача ожидания будет ей предоставлена). Поэтому неудивительно, что иногда задачи 0, 1 и 2 завершаются до того, как задача 3 получает семафор, а иногда все происходит в другом порядке.
Если вы добавляете дополнительные записи в тот момент, когда каждая задача пытаетсячтобы получить семафор, фактически получить его, затем выпустить его, что должно сделать его немного более понятным - вы сможете увидеть, как одна задача выпустит его, а затем другая задача сразу же подхватит его).