2016-06-21 12 views
-1

C#を学ぶために、特定のポートでUDPトラフィックを継続的に監視し、受信したパケット情報でWPF UIテキストブロックを更新するアプリケーションを作成しています。次のコードは、(範囲内の他の場所でインスタンス化されたUDPハンドラクラスのインスタンスd)作品:イベント駆動型WPF UIの更新とC#での非同期受信のベストプラクティスは?

public MainWindow() 
    { 
     InitializeComponent(); 

     Task.Run(async() => 
     { 
      using (d.receiveClient) 
      { 
       while (true) 
       { 
        var receivedResults = await d.receiveClient.ReceiveAsync(); 
        byte[] buffer = receivedResults.Buffer; 
        Console.Write("Receiving Data: "); 
        Console.WriteLine(buffer[0].ToString()); 

        Dispatcher.BeginInvoke(new Action(delegate 
        { 
         MyTextBlock.Text = "Rx Data: " + buffer[0].ToString(); 
        })); 
       } 
      } 
     }); 
    } 

それは動作しますが、それは慣用的な、または正しい感じない確かです。私は今receiveClientが含まれているクラスで非同期受信ロジックを含むTask<byte[]>を作成したいと思います。問題はそれが連続して実行されないということです。タスクは1回実行された後、終了します。私は.ContinueWith()などでタスクを再開しようとしましたが、タスクを再起動することができますが、私はUIにフックを緩めているようです。どのようなイベントを駆動するための最善の方法は、順番にWPFのUIコンポーネントをネイティブC#で更新する(私はむしろWinPcapまたはその同等の.NETを使用したいと思います)?

+0

これは購読/イベントの状況なので、Reactive Extensionsが最善の策になるでしょう。 –

+0

タスクが終了しないので、私はタスクの代わりにスレッドを使用します。メッセージングを使用してUIに更新通知を送信することを検討できます。 MVVM Light Messengerをご覧ください。 – unkreativ

+0

Downvoters - 私は明らかに私が知らないものを知りません。なぜこれが貧しい質問であるのか分からなくてはなりません。書かれているように、タスクは決して終了しません - これは私が望むものです。クラスインスタンスのTaskメソッドと同じものをカプセル化します。私は掲示された振る舞いをしたいが、方法として。もっと重要なのは、私のコードが現在うまく動作しているにもかかわらず、正しく実行する方法を学びたいと思っています。訂正のない下降詞は私が何も学ばないことを保証する。 @unkreativとStephen Cleary、指示に感謝します。私は両方のあなたの提案を調査します。 – user631644

答えて

1

常に実行中のタスク/スレッドを使用してメッセージをメインアプリケーションに戻すのではなく、BeginReceive()EndReceive()メソッドを使用して、データ解析のカスタムイベントを使用することを選択しました。本質的に(本質に蒸留)は、以下のようなもの:

public void Listen() 
    { 
     receiveClient.BeginReceive(new AsyncCallback(ProcessIncoming), null); 
    } 

    private void ProcessIncoming(IAsyncResult res) 
    { 

     byte[] rec_bytes = receiveClient.EndReceive(res, ref rec_ep); 
     receiveClient.BeginReceive(new AsyncCallback(ProcessIncoming), null); 

     PacketReceivedEventArgs args = new PacketReceivedEventArgs(); 
     args.IP = rec_ep.Address; 
     args.Port = rec_ep.Port; 
     args.Data = rec_bytes; 
     OnPacketReceived(args); 
    } 

    protected virtual void OnPacketReceived(PacketReceivedEventArgs e) 
    { 
     EventHandler<PacketReceivedEventArgs> handler = PacketReceived; 
     if (handler != null) 
     { 
      handler(this, e); 
     } 
    } 

    public event EventHandler<PacketReceivedEventArgs> PacketReceived; 

    public class PacketReceivedEventArgs : EventArgs 
    { 
     public byte[] Data { get; set; } 
     public IPAddress IP { get; set; } 
     public int Port { get; set; } 
    } 

メインアプリケーション、接続、リスニング、およびパケット処理では、(dは、上記の方法を実装するクラスのインスタンスである)になる:

d.Connect(someIPString, portInt); 
d.PacketReceived += _SomeHandler; 
d.Listen(); 
関連する問題