Page 57 - MSDN Magazine, May 2018
P. 57

Figure 3 The Rewritten SignalR Back End
the percentage of work currently done. You can have as many han- dlers as you need and the server-side SignalR counterpart exposes. Figure 3 shows the full rewrite of the last month column’s SignalR back end, as a Windows Forms client would consume it.
There are a couple of glitches you should be aware of when writing non-Web SignalR clients. First, the client handlers must be fully configured when the connection starts. Specifically, this means that the call to StartAsync should occur after all the due calls to the method On<T> have been made.
Second, keep in mind that you don’t want to run the server-side— and possibly lengthy—operation that SignalR will notify on the same Windows UI thread. That would make the client application unresponsive. To work around the issue, you have to launch the
server-side operation on another thread, shown here:
private void button1_Click(object sender, EventArgs e)
{
Task.Run(() =>
{ var client = new WebClient(); client.UploadString("http://localhost:60000/task/lengthy);
});
Subsequently, when the server-side SignalR hub notifies back, any due changes must be conveyed to the main UI thread before they can take place. You achieve this by using the Invoke method in the client handler. The Invoke method gets a delegate and runs
it on the UI thread, as shown here:
Invoke((Action)((perc) => {
label1.Text = String.Format("{0}%", perc); }));
Figure 4 shows the sample Windows Forms application in action with a label progressively updated as the server-side oper- ation makes any progress.
The Windows Forms application can receive notifications through any of the supported approaches: broadcast, direct connection, groups, single user and streaming. I’ll have more to say about this in a future column.
Wrapping Up
ASP.NET Core SignalR supports the same transport protocols as the previous ASP.NET version, including WebSockets, ServerSent- Events and LongPolling. Furthermore, it supports a binary message protocol in addition to the canonical JSON format.
Like its predecessor, ASP.NET Core SignalR can be called from a variety of different clients—including old-fashioned Windows Forms applications. The key to achieving broad compatibility is support for the .NET Standard 2.0 specification. As we’ve seen in the article, if the client isn’t a .NET Core application, it must be compiled to a version of the .NET Framework that’s compatible with the latest standard.
The minimum version required is .NET Framework 4.6.1. Be sure to check out the source code for this article, which can be found at bit.ly/2FxCKTs. n
Dino Esposito has authored more than 20 books and 1,000 articles in his 25-year career. Author of “The Sabbatical Break,” a theatrical-style show, Esposito is busy writing software for a greener world as the digital strategist at BaxEnergy. Follow him on Twitter: @despos.
thanks to the following Microsoft expert for reviewing this article: Andrew Stanton-Nurse
May 2018 53
_connection.On("initProgressBar", () => {
// Run on the UI thread
Invoke((Action)(() => label1.Text = "0%")); });
_connection.On<int>("updateProgressBar", (perc) => {
// Run on the UI thread
Invoke((Action) (() => label1.Text = String.Format("{0}%", perc))); });
_connection.On("clearProgressBar", () => {
// Run on the UI thread Invoke((Action)(() => {
label1.Text = "100%";
button1.Enabled = true; }));
});
await _connection.StartAsync();
With that in mind, let’s see how to launch the lengthy task discussed in last month’s column and monitor it from within a new Windows Forms application. To get started, after creating the application skeleton, reference the NuGet package named Microsoft.AspNet- Core.SignalR.Client and all of its dependencies, like so:
private static HubConnection _connection;
private async void Form1_Load(object sender, EventArgs e) {
_connection = new HubConnectionBuilder() .WithUrl("http://localhost:60000/progressdemo") .Build();
await _connection.StartAsync(); }
The code runs when the form loads up and establishes the connec- tion with the specified SignalR endpoint. If you intend for exchanged data to be serialized using the MessagePack protocol, add one more line to the configuration code of the connection builder object, as follows:
private async void Form1_Load(object sender, EventArgs e) {
_connection = new HubConnectionBuilder() .WithUrl("http://localhost:60000/progressdemo") .WithMessagePackProtocol()
.Build();
await _connection.StartAsync(); }
The connection object you receive must be further configured with the client-side handlers responsible for refreshing the UI once notifications from the ASP.NET Core SignalR endpoint come back. Here’s that code:
_connection.On<int>("updateProgressBar", (perc) => {
this.Invoke(
(Action) (() => label1.Text = String.Format("{0}%", perc))
});
In the sample code, when the updateProgressBar notification is received, a text label is updated with the received value representing
Figure 4 The Windows Forms Client Application Updated by an ASP.NET Core SignalR Hub
msdnmagazine.com
}


































































































   55   56   57   58   59