WPFからSignalRでサーバーとリアルタイム通信
前回はサーバとブラウザ間でSignalRを用いた通信を試してみました.
今回は,デスクトップアプリケーションからSignalRを使ってサーバーと通信してみます.
チュートリアルは以下の公式サイトが参考になるでしょう.
環境
- Windows 10 pro 1906
- Visual Studio 2019 16.4 preview1
- dotnet core 3.0.100
書き方などはブラウザでやったのとほとんど同じです.
まずはNugetでMicrosoft.AspNetCore.SignalR.Client
をインストールします.
次にHubConnectionのインスタンスを作成します.
public MainWindow() { InitializeComponent(); //接続のためのHubConnectionのインスタンスを作成する. connection = new HubConnectionBuilder() .WithUrl(@"https://localhost:44350/chathub")//サーバー側でMapHubで指定したURLを指定する. .Build(); }
次にサーバー側から呼び出される処理をHubConnection.On
メソッドを使って登録しておく.
受け取るデータの種類,個数を型引数で指定し,サーバーから呼び出すための名前を指定し,メッセージを受け取ったときの処理を登録します.
下の例はサーバー側からReceive
(大文字小文字は関係ない)という名前で呼び出すことができ,引数は文字列(string)
一つ.
//サーバー側から呼び出される処理を定義 //サーバー側からReceiveを指定して呼び出しがあったときに, //登録したDelegateが実行される. connection.On<string>("Receive", (message) => { //Dispatcher使っている理由は? //UIに直接書き込むのであればUIスレッドで行う必要があるため this.Dispatcher.Invoke(() => { var newMessage = $"{message}"; messagesList.Items.Add(newMessage); }); });
(注意) connection.Onメソッドでの処理の登録はイベントハンドラと同じで累積していきます. 同じ記述が実行されるたびに2つ,3つと累積していくので,同じメッセージが1回で2つ,3つドバっと送られることになります. なのでちゃんと管理しておく必要があります.
特定の登録を削除したい場合はconnection.Remove("Receive")
のように処理につけた名前を指定することで一括削除されます
と,これだけ用意すれば,クライアントサーバー間でリアルアイム通信する準備は整いました.
あとは,以下のメソッドでサーバーとSignalRで接続されます.
await connection.StartAsync();
それでは実行してみましょう.
それぞれのプロジェクトをCtrl+F5で実行します.
ブラウザ側はhttps://localhost:<<port番号>>/index.html
を開きます.
WPF側は最初に接続
ボタンを押して,サーバーと接続します.Connection started
と表示されたら,テキストボックスに文字を入力して送信
ボタンを押せば,メッセージが送信されます.
このようにブラウザ,WPF両方のクライアントにお互いのメッセージが表示されることが確認できます.
おわりに
リアルタイム双方向通信がこんなに簡単にできてしまうなんて素晴らしいですね.
しかも,クライアント側の処理の書き方がC#とJavascriptで同じように書けるというのも,開発コストが低くて良いです.
クライアント側の基本的な書き方が,
- HubのURLを指定
- connection.Onで処理を記述
- connection.StartAsyncで開始
ととてもシンプルです.
今後の発展としては以下が考えられます.
- 接続が切れたときに自動再接続されるようにする
- stringなどの基本型ではなく任意のオブジェクトを受け渡しする
- サーバーからのメッセージをReactive Extensionで扱う
- Azure SignalRを使う