Собрались в кучу async streams, евенты, rx, и даже gRPC.
Можешь попробовать System.Threading.Channels, просто нужно будет создать по каналу на каждое направление.
С ними как раз взаимодействие происходит через async streams.
Дальше буду называть синхронизатор "агентом", а пользователя "контроллером".
Если произошло исключение, то "агент" отправляет соответствующее сообщение "контроллеру" и ждёт от него команду, что делать дальше.
Если "контроллер" посылает команду на завершение работы, то оба канала закрываются и "агент" выключается.
Если "контроллер" посылает команду на продолжение работы, то "агент" возвращается к работе.