クライアントからサーバメソッドを呼び出す際にMicrosoftのページを見て作っていたら
クライアントからサーバのメソッドを呼び出す際にちょっと困ったことになったのでメモ
(そもそも参考ページをあまり理解していないせいかもしれない)
以下参考にしたページです
「ASP.NET SignalR Hubs API ガイド - .NET クライアント (C#)」
クライアント側のプロジェクト
今回実行したいのは、この「メソッドAB呼出」ボタンです
ボタンを押したときに、サーバ側にあるメソッドAとメソッドBを連続して呼び出します
ClientForm.cs
using System.Windows.Forms;
namespace SignalRClientTest
{
public partial class ClientForm : Form
{
public ClientForm()
{
InitializeComponent();
}
/// <summary>
/// 接続ボタンクリック
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ConnectButton_Click(object sender, EventArgs e)
{
bool result = SignalRClient.Connect();
if (result)
MessageBox.Show("接続成功");
else
MessageBox.Show("接続失敗");
}
/// <summary>
/// 切断ボタンクリック
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DisConnectButton_Click(object sender, EventArgs e)
{
SignalRClient.DisConnect();
}
private void CallAB_Click(object sender, EventArgs e)
{
TalkRichTextBox.Text += SignalRClient.CallMethodA();
TalkRichTextBox.Text += SignalRClient.CallMethodB();
}
}
}
「メソッドAB呼出」ボタンの押下で上記のCallAB_Clickメソッドを実行します
画面に配置されたリッチテキストボックスに、CallMethodAとCallMethodBの戻り値が
表示される想定です
SignalRClientTest.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace SignalRClientTest
{
class SignalRClient
{
private static HubConnection hub;
private static IHubProxy proxy;
private const string URL = "http://localhost:8088";
private const string HUB_CLASS = "TestHub";
/// <summary>
/// 接続処理
/// </summary>
/// <returns>結果 true:成功 false:失敗</returns>
public static bool Connect()
{
try
{
hub = new HubConnection(URL);
proxy = hub.CreateHubProxy(HUB_CLASS);
hub.Start().Wait(); // 接続実行
}
catch
{
// 接続失敗
return false;
}
return true;
}
/// <summary>
/// 切断処理
/// </summary>
public static void DisConnect()
{
hub?.Stop();
hub?.Dispose();
}
public static string CallMethodA()
{
string retStr = proxy.Invoke<string>("MethodA").Result;
return retStr;
}
public static string CallMethodB()
{
string retStr = proxy.Invoke<string>("MethodB").Result;
return retStr;
}
}
}
参考ページ記載の
「戻り値を持ち、複合型パラメーターを受け取るメソッドを同期メソッドで呼び出すクライアント コード」
を動かしてみます
proxy.Invokeに「.Result」を付与して戻り値を返却してくれるサーバメソッドを呼び出します
サーバ側のプロジェクト
サーバ側はとりあえずハブクラスだけ記載します
TestHub.cs
namespace SignalRServerTest
{
public class TestHub : Hub
{
public string MethodA()
{
return "A";
}
public string MethodB()
{
return "B";
}
}
}
MethodAが呼び出されたら「A」という文字が返却される
MethodBが呼び出されたら「B」という文字が返却される
という非常にシンプルなものになっています
期待する結果としては、
クライアント側で「メソッドAB呼出」ボタンをクリックすると
リッチテキストボックスに「AB」と表示される動作となります
動かしてみる
サーバとクライアントを実行してサーバを開始、クライアントから接続までしておきます
「メソッドAB呼出」ボタンをクリックしてみました
リッチテキストボックスには「A」しか表示されていません
ちなみにこのときクライアント側のウィンドウで、カーソルがくるくる(砂時計)していました
メソッドBの戻り値が返ってこない…
ブレークポイントを貼ってステップ実行してみます
MethodAの呼び出しは通ったので、MethodAは無事呼べたようです
次にMethodBの呼び出しに移ります
どっかいっちゃいました
この「proxy.Invoke<string>("MethodB").Result」を実行したら
カーソルがくるくるしてずっと待つ羽目になるようです
ちなみにサーバ側のMethodBにもブレークポイントを貼っていたのですが
止まらなかったので呼び出されてもいないようです
ちゃんと2つとも呼び出される奴に直す
ClientForm.cs
using System.Windows.Forms;
namespace SignalRClientTest
{
public partial class ClientForm : Form
{
public ClientForm()
{
InitializeComponent();
}
/// <summary>
/// 接続ボタンクリック
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ConnectButton_Click(object sender, EventArgs e)
{
bool result = SignalRClient.Connect();
if (result)
MessageBox.Show("接続成功");
else
MessageBox.Show("接続失敗");
}
/// <summary>
/// 切断ボタンクリック
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DisConnectButton_Click(object sender, EventArgs e)
{
SignalRClient.DisConnect();
}
private async void CallAB_Click(object sender, EventArgs e)
{
TalkRichTextBox.Text += await SignalRClient.CallMethodA();
TalkRichTextBox.Text += await SignalRClient.CallMethodB();
}
}
}
CallAB_Clickメソッドにasyncをつけます
MethodAとMethodBを呼び出してくれるメソッドに
awaitをくっつけて、呼出処理を待ってもらいます
SignalRClientTest.cs
using System.Threading.Tasks;
namespace SignalRClientTest
{
class SignalRClient
{
private static HubConnection hub;
private static IHubProxy proxy;
private const string URL = "http://localhost:8088";
private const string HUB_CLASS = "TestHub";
/// <summary>
/// 接続処理
/// </summary>
/// <returns>結果 true:成功 false:失敗</returns>
public static bool Connect()
{
try
{
hub = new HubConnection(URL);
proxy = hub.CreateHubProxy(HUB_CLASS);
hub.Start().Wait(); // 接続実行
}
catch
{
// 接続失敗
return false;
}
return true;
}
/// <summary>
/// 切断処理
/// </summary>
public static void DisConnect()
{
hub?.Stop();
hub?.Dispose();
}
public static async Task<string> CallMethodA()
{
string retStr = await proxy.Invoke<string>("MethodA");
return retStr;
}
public static async Task<string> CallMethodB()
{
string retStr = await proxy.Invoke<string>("MethodB");
return retStr;
}
}
}
こちらも非同期メソッドにします
proxy.Invokeから「.Result」を削除して
awaitをくっつけて処理を待ってもらいます
直したやつを動かしてみる
「メソッドAB呼出」ボタンをクリックすると
リッチテキストボックスに「AB」と表示されました
想定通りの結果となったので成功です
連続してサーバメソッドをクライアントから呼び出すメモ
よくわからないけど.Resultを付与して同期メソッドで呼び出すと
1つめのメソッドはちゃんと呼び出されるが
2つ目のメソッドからうまく呼び出されなくなる
サーバメソッドを連続して呼び出す際には
非同期メソッドで呼び出す必要がある