我正在编写一个 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,然后开始侦听响应。收到它们后,我用结果更新一个名为“clients”(由对象“ClientState”组成)的 ObservableCollection:
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。但是,问题是当我尝试连接到 PropertyChanged... 首先,我添加
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");
}
}
}
}
...所以我希望对“currentState”的任何更改都会触发一个事件。但是,我在同一个地方得到一个错误,除了现在错误是:
你调用的对象是空的。
在r.DataReceived.EndInvoke(result)
cbDataRecievedCallbackComplete 的行中。