之前写了个用Socket来更新多个Winfrom的试例,这两天看了下SignalR,也用这个来试一下
SignalR 地址:https://www.asp.net/signalr
我这个也是基于 https://code.msdn.microsoft.com/Using-SignalR-in-WinForms-f1ec847b 改的
有很多地方基本上不明白,现在也只处在稍微会用的一些阶段
话不多讲,先看代码
1.创建服务端
样子,基本上就这样,先贴代码
里面有两个类文件要注意 MyHub和Startup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
namespace ServerFrm
{
public class MyHub:Hub
{
/// <summary>
/// 在连接上时
/// </summary>
/// <returns></returns>
public override Task OnConnected ()
{
///向服务端写入一些数据
Program.serverFrm.WriteToInfo ( "客户端连接ID:" + Context.ConnectionId);
return base .OnConnected ();
}
public override Task OnDisconnected ( bool stopCalled)
{
///向服务端写入一些数据
Program.serverFrm.WriteToInfo ( "客户端退出ID:" + Context.ConnectionId);
return base .OnReconnected ();
}
/// <summary>
/// 这是给客户来调用的
/// 当客户端的添加按钮点击后
/// 就调用此方法
/// 当在客户端绑定了下面的Update方法后
/// 会自动去调用Update方法
/// </summary>
/// <param name="actionId">操作标识符</param>
public void Send( string actionId)
{
/// 这是给客户端来调用的
/// 在连接服务器之前就给连接代理绑定这个方法
/// 在客户端连接上此服务后
/// 客户端绑定此方法,并且传入一个标识符,本例为 "1"(代表要更新界面上的datagridview
Clients.All.Update (actionId);
}
}
}
|
在MyHub里就只有一个方法是给客户端调用的Send
等会就会在客户端里看到这个方法的调用场景
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup ( typeof (ServerFrm.Startup))]
namespace ServerFrm
{
public class Startup
{
public void Configuration (IAppBuilder app)
{
// 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
//设置可以跨域访问
app.UseCors (Microsoft.Owin.Cors.CorsOptions.AllowAll);
//映射到默认的管理
app.MapSignalR ();
}
}
}
|
1
|
Startup类,基本上我也弄不太明白,反正就这么写也不出错,但不写肯定是错<br><br>接着是服务端主要的代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
using System;
using System.Windows.Forms;
namespace ServerFrm
{
static class Program
{
/// <summary>
/// 创建一个静态的对象,方便给服务端调用
/// </summary>
internal static ServerFrm serverFrm { get ; set ; }
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main ()
{
Application.EnableVisualStyles ();
Application.SetCompatibleTextRenderingDefault ( false );
serverFrm = new ServerFrm ();
Application.Run (serverFrm);
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Owin.Hosting;
namespace ServerFrm
{
public partial class ServerFrm : Form
{
public ServerFrm ()
{
InitializeComponent ();
}
private IDisposable signalR { get ; set ; }
private string serverUrl { get ; set ; } = System.Configuration.ConfigurationManager.AppSettings[ "url" ];
private void btnStart_Click ( object sender , EventArgs e)
{
WriteToInfo ( "正在连接中...." );
btnStart.Enabled = false ;
Task.Run (() =>
{
ServerStart ();
});
}
/// <summary>
/// 开启服务
/// </summary>
private void ServerStart ()
{
try
{
//开启服务
signalR = WebApp.Start (serverUrl);
}
catch ( Exception ex )
{
//服务失败时的处理
WriteToInfo ( "服务开启失败,原因:" + ex.Message);
this .Invoke ( new Action (() =>
{
btnStart.Enabled = true ;
}));
return ;
}
//服务成功,继续下一步
this .Invoke ( new Action (() =>
{
//启用停止按钮
btnStop.Enabled = true ;
}));
WriteToInfo ( "服务开启成功 : " + serverUrl);
}
/// <summary>
/// 向服务容器写入信息
/// </summary>
/// <param name="msg">信息</param>
internal void WriteToInfo( string msg)
{
if ( richTextBox.InvokeRequired )
{
this .Invoke ( new Action (() =>
{
WriteToInfo (msg);
}));
return ;
}
richTextBox.AppendText (msg+Environment.NewLine);
}
private void btnStop_Click ( object sender , EventArgs e)
{
if ( signalR!= null )
{
signalR.Dispose ();
}
}
private void ServerFrm_FormClosing ( object sender , FormClosingEventArgs e)
{
btnStop_Click ( this , new EventArgs ());
Close ();
}
}
}
|
服务端的代码很少,主要的就是开启服务而已
接着是客户端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
using System;
using System.Linq;
using System.Windows.Forms;
using Microsoft.AspNet.SignalR.Client;
using Model;
namespace ClinetFrm
{
public partial class Clinet : Form
{
/// <summary>
/// 连接代理对象
/// </summary>
private IHubProxy hubProxy { get ; set ; }
/// <summary>
/// 绑定的服务器url
/// </summary>
private string ServerURI = System.Configuration.ConfigurationManager.AppSettings[ "url" ];
/// <summary>
/// 连接对象
/// </summary>
private HubConnection hubConnection { get ; set ; }
public Clinet ()
{
InitializeComponent ();
}
private void Clinet_Load ( object sender , EventArgs e)
{
InitData ();
InitHub ();
}
private async void InitHub ()
{
//创建连接对象
hubConnection = new HubConnection (ServerURI);
//绑定一个集线器
hubProxy = hubConnection.CreateHubProxy ( "MyHub" );
//注册服务端的方法,此方法请转至服务端MyHub.cs中查看
hubProxy.On ( "Update" , (a) =>
{
//如果接收到的是"1"
if ( a == "1" )
{
//则更新界面
InitData ();
}
});
try
{
//开始连接
await hubConnection.Start ();
}
catch ( Exception ex )
{
this .Text = "服务器未连接上" ;
return ;
}
this .Text = "服务器已连接上" ;
}
/// <summary>
/// 加载或更新datagridview
/// </summary>
private void InitData ()
{
//获取数据
DemoEntities demo = new DemoEntities ();
var list = demo.DemoTable.ToList ();
this .Invoke ( new Action (() =>
{
//绑定数据
dataGridView1.DataSource = list;
}));
}
/// <summary>
/// 添加按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnAdd_Click ( object sender , EventArgs e)
{
DemoEntities demo = new DemoEntities ();
demo.DemoTable.Add ( new DemoTable ()
{
name = txtName.Text ,
value = txtVal.Text
});
demo.SaveChanges ();
///使用代理启动方法,启动的是服务端中的Send方法
///而在服务端中Send会调用Update方法
///因为我们在程序启动时连接上了服务端
///而且绑定了Update方法,所以服务端在接收到Send方法被调用的通知时
///会自动去广播所有已经连上服务端的客户端使其调用Update方法
hubProxy.Invoke ( "Send" , "1" );
}
private void Clinet_FormClosing ( object sender , FormClosingEventArgs e)
{
if ( hubConnection != null )
{
hubConnection.Stop ();
hubConnection.Dispose ();
}
}
}
}
|
客户端界面
再来张动图演示一下
https://github.com/raozhihao/SignallR4WinformUpdateDemo
git地址
里面用了EF数据库,可以照着Model - > DemoTable.cs 中的字段在数据库中建一个
另外在git中加入了服务端向客户端广播的一些代码