Я думаю, что происходит комбинация двух вещей, которые вместе вызывают тупик.
Во-первых, к полю running
обращаются из нескольких потоков, но они не синхронизируются.Если вы обращаетесь к данным из нескольких потоков, они должны быть заблокированы .В этом случае, после того, как основной поток установит в поле значение false, фоновый поток может некоторое время считать его истинным.
Вторым является то, что вы вызываете Dispatcher.Invoke
, а не Dispatcher.BeginInvoke
.Invoke
отправит сообщение в очередь сообщений диспетчера и будет ждать до тех пор, пока это сообщение не будет обработано, блокируя вызывающий поток.
Итак, что происходит:
- Поток диспетчера устанавливает
running
в false
- Блокирует поток диспетчера, ожидая выхода фонового потока
- Фоновый поток завершает свой сон, неправильно читает
running
as true
, отправляет сообщение в очередь сообщений потока диспетчера и блокирует ожидание его обработки - Сообщение никогда не будет обработано, поскольку поток диспетчера блокируется в ожидании выхода фонового потока
- Фоновый поток никогда не завершится, потому что он заблокирован в ожидании обработки сообщения потоком диспетчера
- Deadlock
Это происходит потому, что вы 'нарушая ряд различных кардинальных правил:
- Никогда не блокируйте поток пользовательского интерфейса.Всегда.
- Никогда не обращайтесь к общему состоянию из двух потоков без блокировки (или другой синхронизации).Когда-либо.
- Используйте Invoke поверх BeginInvoke только в том случае, если у вас есть действительно веская причина.
Как говорится в комментариях, используйте для этого DispatcherTimer.
Если вам действительно нужно отменить фоновую ветку, используйте CancellationToken
.