事件处理程序递增循环问题

3
我正在使用Xamarin.Forms创建聊天机器人应用程序。每当我向机器人发送新消息时,都会收到回复,但是它会自动加一,例如:
User: Hi
Bot: Hello
User: How are you?
Bot: Good
Bot: Good

在我的代码中,我使用了以下内容:
 public void Send()
        {
            if (!string.IsNullOrEmpty(TextToSend))
            {
                //This adds a new message to the messages collection
                Messages.Add(new ChatMessageModel() { Text = TextToSend, User = App.User });

                //This gets the chatbots response for each message
                chatbot.MainUser.ResponseReceived += async (sender, args) =>
                {
                    await Task.Delay(1500);
                    Messages.Add(new ChatMessageModel() { Text = args.Response.Text, User = App.ChatBot });
                };

                var result = chatbot.Evaluate(TextToSend);
                result.Invoke();

                //Removes the text in the Entry after message is sent
                TextToSend = string.Empty;
            }
        }

使用Messages.Add(new ChatMessageModel() { Text = args.Response.Text, User = App.ChatBot });断点后,我发现它每次都会添加一条新消息,因此会不断累加。我想找到一种方法来停止这种情况,只让它发生一次。
编辑:整个类
using BluePillApp.Models;
using BluePillApp.ViewModels.Base;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Windows.Input;
using Xamarin.Forms;
using Syn.Bot.Siml;
using Syn.Bot.Oscova;
using Syn.Bot.Oscova.Attributes;
using System.Reflection;
using System.IO;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace BluePillApp.ViewModels
{
    /// <summary>
    /// View model for the ChatbotPage.xaml
    /// </summary>
    public class ChatbotPageViewModel : BaseViewModel
    {
        /// <summary>
        /// A field for TextToSend
        /// </summary>
        private string _texttosend;

        /// <summary>
        /// An Instance of a new SIML Oscova Chatbot
        /// </summary>
        public OscovaBot chatbot;

        /// <summary>
        /// A collection/list of chat message items
        /// </summary>
        public ObservableCollection<ChatMessageModel> Messages { get; set; } = new ObservableCollection<ChatMessageModel>();

        /// <summary>
        /// The text that the user inputs
        /// </summary>
        public string TextToSend
        {
            get
            {
                return _texttosend;
            }

            set
            {
                if (_texttosend != value)
                {
                    _texttosend = value;

                    OnPropertyChanged();
                }
            }
        }

        /// <summary>
        /// A command for sending the users messages
        /// </summary>
        public ICommand SendCommand { get; set; }


        /// <summary>
        /// ChatPageViewModel Constructor
        /// </summary>
        public ChatbotPageViewModel()
        {
            SendCommand = new RelayCommand(Send);

            chatbot = new OscovaBot();
            var assembly = IntrospectionExtensions.GetTypeInfo(typeof(MainPage)).Assembly;
            Stream stream = assembly.GetManifestResourceStream("BluePillApp.Helpers.new.siml");

            chatbot.Import(XDocument.Load(stream));
            chatbot.Trainer.StartTraining();
        }

        /// <summary>
        /// This function sends a message
        /// </summary>
        public void Send()
        {
            if (!string.IsNullOrEmpty(TextToSend))
            {
                var msgModel = new ChatMessageModel() { Text = TextToSend, User = App.User };
                //This adds a new message to the messages collection
                Messages.Add(msgModel);

                //This gets the chatbots response for each message
                chatbot.MainUser.ResponseReceived += async (sender, args) =>
                {
                    await Task.Delay(1500);
                    Messages.Add(new ChatMessageModel() { Text = args.Response.Text, User = App.ChatBot });
                };

                var result = chatbot.Evaluate(TextToSend);
                result.Invoke();

                //Removes the text in the Entry after message is sent
                TextToSend = string.Empty;
            }
        }
    }
}

2个回答

3
每次调用Send时,您都会添加一个新的事件处理程序。
chatbot.MainUser.ResponseReceived +=

你只需要分配一次这个事件处理程序


我怀疑是这样的。我该如何只调用一次此事件处理程序? - Hitman DD
将其设置在Send方法之外。构造函数可能是一个不错的地方。 - Jason
这个运行得非常好,我努力思考了很长时间才想出来,其实相当简单。谢谢。 - Hitman DD

1
你的调试非常出色,现在尝试保存那个该死的对象:
var msgModel = new ChatMessageModel() { Text = TextToSend, User = App.User };

//This adds a new message to the messages collection
Messages.Add(msgModel);

然后重新使用它:
//This gets the chatbots response for each message
chatbot.MainUser.ResponseReceived += async (sender, args) =>
{
    msgModel.Text = args.Response.Text;
    msgModel.User = App.ChatBot;
    await Task.Delay(1500);
    Messages.Add(msgModel);
};

我希望这可以解决问题。


末尾的Messages.Add();给我一个错误:“没有对应所需形式参数'item'的参数”。 - Hitman DD
抱歉,现在已经修复了。 - Alb
是的,我刚试了一下,仍然遇到了同样的问题,它还导致我的用户界面出现了一些错误。 - Hitman DD
我现在有一个不同的想法。尝试保留你的原始代码,但删除 "result.Invoke();",因为 invoke 意味着 "调用/调用方法",所以我假设它会对 "chatbot.Evaluate()" 进行第二次调用,并导致双重输出。 - Alb
这对我也没用。在这种情况下,InvokeEvaluate方法是我使用的外部框架的方法,它们必须一起使用才能正常工作。有可能与事件处理程序有关吗? - Hitman DD
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接