使用事件驱动的 TCP 客户端和 NotifyPropertyChanged 一起会导致异常

本文关键字:一起 异常 NotifyPropertyChanged 事件驱动的 TCP 客户端 | 更新日期: 2023-09-27 18:36:32

我正在编写一个 C# 控制台应用程序,该应用程序通过 TCP 连接到服务器并定期接收数据。我正在使用我在这里找到的一些代码,这是一个很好的易于使用的异步客户端。使用它,我的代码启动,建立连接,然后等待事件:

static void Main(string[] args)
        {
            agents = new ObservableCollection<AgentState>();
            EventDrivenTCPClient client = new EventDrivenTCPClient(IPAddress.Parse("192.168.0.1"), 5000);
            client.DataReceived += new EventDrivenTCPClient.delDataReceived(client_DataReceived);
               client.Connect();
                do
                {
                    while (!Console.KeyAvailable)
                    {
                        Thread.Sleep(50);
                    }
                } while (Console.ReadKey(true).Key != ConsoleKey.Q);
client.Disconnect();
       }

这将启动应用,连接到端口 5000 上的 192.168.0.1,然后开始侦听响应。收到它们后,我会使用结果更新一个名为"client"(由对象"ClientState"组成)的可观察集合:

 static void client_DataReceived(EventDrivenTCPClient sender, object data)
    {
               string received = data as string;
        string parameters=received.Split(',');
        ClientState thisclient = clients.FirstOrDefault(a => a.clientName == parameters[0]);
        var index = clients.IndexOf(thisclient);
        if (index < 0)
        {
            ClientState newclient = new ClientState();
            newclient.clientName = clientname;
            newclient.currentState = state;
            newclient.currentCampaign = campaign;
            clients.Add(newclient);
        }
        else
        {
            clients[index].currentState = state;
            clients[index].currentCampaign = campaign;
        }
    }

令我非常惊讶的是,这一切都运行良好:代码滴答作响,收集统计数据并添加和更新 ObservableCollection。但是,问题是当我尝试挂接到属性更改时...首先,我补充

   clients.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(agents_CollectionChanged);

到 Main(),然后我添加:

    static void clients_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
                 foreach (INotifyPropertyChanged item in e.NewItems)
                     item.PropertyChanged += new PropertyChangedEventHandler(newagent_PropertyChanged); 
    }

我希望这在 ObservableCollection 中的任何更改时调用 newagent_PropertyChanged 方法(目前只是向控制台吐出)......但出于某种原因,一旦触发 PropertyChanged 事件,我在 TCP 代码中的"cbDataRecievedCallbackComplete"方法中得到异常:

无法将类型为"ClientState"的对象强制转换为类型"System.ComponentModel.INotifyPropertyChanged"。

。因此,不知何故,尝试引发 PropertyChanged 的行为导致"cbDataRecievedCallbackComplete"代码触发;就好像事件是"交叉路径"。如果我"捕获"错误,代码就会停止并且不再处理任何传入数据。

我没有足够的经验来知道这是我引入的问题,还是源代码的问题。我会把钱放在前者上:谁能看出问题出在哪里?

更新:为了响应下面的答案,我将我的类定义更改为如下所示:

  public class ClientState : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
        public string agentName { get; set; }
        public string currentCampaign { get; set; }
        public string _currentState;
        public string currentState
        {
            get { return _currentState; }
            set
            {
                if (value != _currentState)
                {
                    _currentState = value;
                    OnPropertyChanged("CurrentState");
                }
            }
        }
    }

。所以我希望对"当前状态"的任何更改都会触发事件。但是,我在同一个地方收到错误,但现在错误是:

对象引用未设置为对象的实例。

在 cbDataRecievedCallbackComplete 的r.DataReceived.EndInvoke(result)行中。

使用事件驱动的 TCP 客户端和 NotifyPropertyChanged 一起会导致异常

如果你的 ClientState 的类定义看起来不像这样

public class ClientState : INotifyPropertyChanged

则不能将其强制转换为类型"INotifyPropertyChanged"。 您不会收到编译时异常,因为 e.NewItems 集合是对象类型,因此它会允许您尝试将其强制转换为任何内容。

异常将由以下行引起:

foreach (INotifyPropertyChanged item in e.NewItems)

您正在隐式地将每个对象转换为e.NewItems INotifyPropertyChanged。由于e.NewItems包含ClientState的实例,我猜测ClientState没有实现INotifyPropertyChanged