TCP 経由でサーバーに接続し、定期的なデータを受信する C# コンソール アプリケーションを作成しています。ここで見つけたコードを使用しています。これは、使いやすい非同期クライアントです。これを使用して、コードが起動し、接続を確立してからイベントを待機します。
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」という名前の ObservableCollection (オブジェクト「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 に追加および更新します。ただし、問題は 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の行にあります。