TCPを介して組み込みデバイスを制御するためのwpfアプリケーションを作成しています。デバイスへの書き込みは簡単ですが、パケットの受信に問題があります。
tcp NetworkStreamを作成し、NetworkStream.BeginRead()を使用してTCPデータをリッスンしています。ただし、完全なパケットを作成したら、新しい情報を反映するようにGUIを更新したいと思います。非同期コールバックスレッドからこれを行うことは許可されていないようです。
ディスパッチャを介して一度に1つのリクエストでこれを行う方法があるようですが、GUIの実質的にすべてのコントロールを更新する必要があります。すべてのパケットケースとすべてのWPFコントロールに対してディスパッチャー関数を作成しているわけではありません。非同期スレッドからWPFコントロールに完全にアクセスするにはどうすればよいですか?
編集: ここにコードサンプルがあります:
NetworkUnion union = (NetworkUnion)ar.AsyncState;
union.BytesRead += tcpStream.EndRead(ar);
if (union.BytesRead < union.TargetSize)
tcpStream.BeginRead(union.ByteArray, union.BytesRead, union.TargetSize - union.BytesRead, new AsyncCallback(ReadCommandCallback), union);
else
{
NetworkUnion payload = new NetworkUnion();
NetworkPacket pkt = (NetworkPacket)union.getArrayAsStruct();
// Respond to the packet
// Read the payload
payload.ByteArray = new byte[pkt.payloadSize];
tcpStream.Read(payload.ByteArray, 0, pkt.payloadSize);
// Determine what the payload is!
switch (pkt.code)
{
case (int)PacketCode.STATE:
payload.ObjectType = typeof(NetworkState);
NetworkState state = (NetworkState)payload.getArrayAsStruct();
Handle.fuelGauge.Value = Convert.ToDouble(state.mainFuel);
break;
残量ゲージを更新しようとすると、InvalidOperationExceptionが発生します。別のスレッドがオブジェクトを所有しているため、呼び出し元のスレッドはアクセスできません。
'Handle'変数が使用されるのは、これが静的ユーティリティクラス内からのものであるためです。
主な質問は、私は本当にすべての行を置き換える必要がありますか?
Handle.fuelGauge.Value = Convert.ToDouble(state.mainFuel);
と
Handle.fuelGauge.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
Handle.fuelGauge.Value = Convert.ToDouble(state.mainFuel);
}
));
?繰り返しが多すぎるようです。次のようなことを行う方が簡単です。
Handle.mainWindow.Dispather.Lock();
Handle.fuelGauge.Value = Convert.ToDouble(state.mainFuel);
change everything else...
Handle.mainWindow.Dispatcher.Unlock();