【问题标题】:Event handler incrementing loop issue事件处理程序递增循环问题
【发布时间】:2020-02-16 02:21:34
【问题描述】:

我正在使用 Xamarin.Forms 创建聊天机器人应用。每当我向机器人发送新消息时,都会收到回复,但会自行增加 1,即

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;
            }
        }
    }
}

【问题讨论】:

    标签: c# xamarin events event-handling


    【解决方案1】:

    每次您拨打Send 时,您都会添加一个事件处理程序

    chatbot.MainUser.ResponseReceived +=
    

    您应该只需要分配此事件处理程序ONCE

    【讨论】:

    • 我怀疑是这样的。这个事件处理程序如何处理一次?
    • 在您的 Send 方法之外设置它。构造函数可能是个好地方。
    • 这非常有效,我绞尽脑汁想弄清楚这个问题已经很久了,其实很简单。谢谢
    【解决方案2】:

    你调试得很好,现在试着保存那个该死的对象:

    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'”
    • 抱歉,已经修复了。
    • 是的,刚刚试了一下,还是遇到了同样的问题,这也让我的 UI 出了点问题。
    • 我现在有了不同的想法。尝试保留您的原始代码,但删除“result.Invoke();”因为invoke的意思是“调用/调用一个方法”,所以我假设它第二次调用“chatbot.Evaluate()”并导致双输出。
    • 这对我也不起作用。在这种情况下,InvokeEvaluate 方法是我正在使用的外部框架的方法,它们必须在一起才能工作。有没有可能与事件处理程序有关?
    猜你喜欢
    • 2015-04-05
    • 2011-05-16
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    • 2018-08-18
    • 2011-11-03
    相关资源
    最近更新 更多