В этом коде есть несколько проблем.
Источник описываемой вами проблемы:
tasks.Add(Task.Run(async () =>
{
while (!CancellationTokenSrc.Token.IsCancellationRequested)
Задачи всегда проверяют токен текущего CancellationTokenSrc
.Так что, если отмена не произойдет в точный момент между Task.Delay
вызовами, когда задачи проверяют IsCancellationRequested
, они просто увидят новый, не отмененный CTS, который вы создадите после перезапуска.
Вы должны передать текущий CancellationToken
в качестве аргумента метода или сохраните его в локальной переменной внутри M_Start
вместо проверки общего поля CancellationTokenSrc
, чтобы избежать этой проблемы.
Небольшое улучшение: Task.Delay
также имеет перегрузку, которая принимаетCancellationToken
.Он выдаст TaskCanceledException
.
. Кроме того, вы обновляете свойства OutputX
из параллельных потоков (Task.Run
), которые затем вызывают событие PropertyChanged
, которое должно обновлять пользовательский интерфейс.Этот вид межпотокового взаимодействия с пользовательским интерфейсом небезопасен, вам нужно будет задействовать Dispatcher
, чтобы убедиться, что событие вызвано в потоке пользовательского интерфейса.
Наконец, владение CancellationTokenSrc
довольносложный и кажется созревшим для условий гонки, так как несколько параллельных методов используют и устанавливают его.В случае перезапуска M_Start
может легко вызвать NullReferenceException
при попытке отменить CancellationTokenSrc
, для которого уже установлено значение null
в StartToMonitor
.