Получение нескольких сообщений в быстрой последовательности может быть проблемой, и может быть трудно понять, как ваш бот должен справиться с этим. Предположим, у вас есть диалоговое окно с водопадом, в котором отображается запрос подтверждения типа «Довольны ли вы этим?»на шаге 1, и пользователь дважды говорит «да» в двух разных сообщениях, которые затем обрабатывает ваш бот. Что случится? Ну, есть две возможности:
- Если оба потока загружают состояние бота до того, как один из них сохранит состояние бота, то они оба будут одинаково обрабатывать ход и обрабатывать шаг 2 дважды. Это означает, что любой запрос на шаге 2, например "Хорошо, вам нужно что-нибудь еще?"будет отображаться дважды. Состояние бота будет одинаковым в обоих потоках, поэтому после того, как они оба сохранят состояние бота, бот все равно будет на шаге 2. Это не так уж плохо, потому что пользователь может просто интуитивно ответить на приглашение и перейти к шагу3.
- Если первый поток обрабатывает шаг 2 так быстро, что сохраняет состояние бота до того, как второй поток загрузит состояние бота, то второй поток будет воспринимать второе «да» пользователя как ответ на шаг 2вместо шага 1. Так что, если на шаге 2 есть еще один запрос подтверждения типа «Хорошо, вам нужно что-нибудь еще?»тогда второе «да» будет рассматриваться как ответ на запрос подтверждения шага 2 вместо запроса подтверждения шага 1, и бот отобразит шаг 3. Это может быть плохо, если пользователь не хочет сказать «да» второмуподсказка, но эту проблему можно решить с помощью хороших опций навигации. В качестве альтернативы, если на шаге 2 есть какой-то другой вид подсказки, такой как подсказка выбора, и он не распознает «да» в качестве опции, второй поток просто отобразит подсказку повтора, и бот останется на шаге 2. Опять жеЭто не так плохо, потому что тогда у пользователя будет возможность правильно ответить на приглашение.
Как видно из комментариев, есть много возможностей для решения этой проблемы. Прямо сейчас я скажу, что рекомендуемое решение - оставить проблему в покое и просто позволить боту продолжить работу. Это потому, что обычно это не достаточно большая проблема, о которой нужно беспокоиться, и пользователь быстро пойметчто им нужно замедляться и вводить сообщения по одному. Если вам необходимо решить проблему, вы уже видели несколько возможных решений, упомянутых в комментариях, и они включают как решения на стороне клиента, так и решения на стороне бота. Теперь я сосредоточусь на решениях на стороне бота, поскольку вы сказали, что это все, что вы ищете.
Вариант 1. Отправьте индикатор ввода
Многие каналы имеют индикатор, который позволяет пользователям знать, чтокто-то печатает. Боты Bot Framework могут смоделировать это, используя тип активности «печатать». Существует промежуточное программное обеспечение, которое обрабатывает это для вас , и оно встроено в Bot Builder SDK. Вы можете посмотреть его исходный код, чтобы увидеть, как вручную отправлять операции ввода.
Вариант 2: Отправить предупреждающее сообщение
Если вы знаете, что боту потребуется некоторое время для обработкисообщение пользователя, вы можете пойти дальше и отправить сообщение обратно пользователю, прежде чем бот выполнит его длительную обработку. Это позволит пользователю знать, что он не должен отправлять больше сообщений боту, пока не получит реальный ответ. Это служит той же цели, что и опция 1, и может использоваться вместе с ней, чтобы придать ей дополнительный вес.
Вариант 3: Отслеживать одновременные потоки с состоянием бота
Эта опцияне рекомендуется, но это то, что вы изначально просили. Чтобы бот знал, что он в настоящее время обрабатывает сообщение от пользователя в другом потоке, первый поток должен сохранить что-то в состоянии бота, которое указывает второму потоку, что бот обрабатывает сообщение. Это грязный и сложный процесс, склонный к сбоям, и вам нужно будет беспокоиться обо всех обычных проблемах с многопоточностью, таких как состояние гонки и тупики. Это должно было бы пойти что-то вроде этого:
- Когда бот начинает обрабатывать сообщение, он читает специальное свойство из состояния бота (т. Е. Состояния разговора, состояния пользователя или чего-либо еще). Это свойство может выступать в качестве семафора, который считает от 0 до 1, когда бот пишет в него, или может действовать как обычная блокировка, которая имеет значение true или false, в зависимости от того, обрабатывает ли бот сообщение в этом диалоге. Это может произойти в некотором пользовательском промежуточном программном обеспечении или даже в специальном адаптере.
- Если бот читает свойство и указывает, что в данный момент никакие другие потоки не обрабатывают никаких сообщений в этом диалоге, бот должен немедленно изменитьэто свойство и записать его в хранилище. Именно здесь могут вступить в игру условия гонки, потому что два потока могут попытаться прочитать значение, прежде чем кто-либо из них запишет его, и тогда они оба подумают, что должны продолжить. Вам нужно было бы протестировать хранилище состояний, чтобы убедиться, что оно может адекватно блокировать запись каждого разговора, чтобы этого не происходило.
- Затем бот продолжит обрабатывать ход как обычно.
- Бот должен убедиться, что он меняет специальное свойство обратно на то, что было раньше, когда он завершил обработку, поэтому он будетиметь возможность обрабатывать сообщения снова на следующем ходу. Это действительно важно, поэтому вы должны также сделать это в обработчике ошибок вашего адаптера. Даже тогда, есть вероятность, что свойство не будет изменено обратно, и это сломает вашего бота. Возможно, вы захотите придумать способ заставить его автоматически переключаться обратно через некоторое время.
- Если бот читает свойство и указывает, что другой поток обрабатывает сообщение,затем он отправит пользователю сообщение «Пожалуйста, подождите, я все еще ищу ответ» и завершите ход.
См. также этот документ по устранению неполадок