以前寫了個用Socket來更新多個Winfrom的試例,這兩天看了下SignalR,也用這個來試一下git
SignalR 地址:https://www.asp.net/signalrgithub
我這個也是基於 https://code.msdn.microsoft.com/Using-SignalR-in-WinForms-f1ec847b 改的數據庫
有不少地方基本上不明白,如今也只處在稍微會用的一些階段跨域
話很少講,先看代碼服務器
1.建立服務端app
樣子,基本上就這樣,先貼代碼asp.net
裏面有兩個類文件要注意 MyHub和Startupasync
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裏就只有一個方法是給客戶端調用的Sendide
等會就會在客戶端裏看到這個方法的調用場景ui
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 (); } } }
Startup類,基本上我也弄不太明白,反正就這麼寫也不出錯,但不寫確定是錯<br><br>接着是服務端主要的代碼
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); } } }
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 (); } } }
服務端的代碼不多,主要的就是開啓服務而已
接着是客戶端
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中加入了服務端向客戶端廣播的一些代碼