• 利用SignalR来同步更新Winfrom小试


    之前写了个用Socket来更新多个Winfrom的试例,这两天看了下SignalR,也用这个来试一下

    SignalR 地址:https://www.asp.net/signalr

    我这个也是基于 https://code.msdn.microsoft.com/Using-SignalR-in-WinForms-f1ec847b 改的

    有很多地方基本上不明白,现在也只处在稍微会用的一些阶段

    话不多讲,先看代码

    1.创建服务端

    样子,基本上就这样,先贴代码

    里面有两个类文件要注意 MyHub和Startup

    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

    等会就会在客户端里看到这个方法的调用场景

    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类,基本上我也弄不太明白,反正就这么写也不出错,但不写肯定是错

    接着是服务端主要的代码
    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中加入了服务端向客户端广播的一些代码

  • 相关阅读:
    怎样克服 JavaScript 框架疲劳?
    jQuery 简单归纳总结
    锋利的JQuery —— 事件和动画
    锋利的JQuery —— DOM操作
    锋利的JQuery —— 选择器
    Maven日常 —— 你应该知道的一二三
    《时间简史》—— 读后总结
    Elasticsearch之_default_—— 为索引添加默认映射
    Elasticsearch 动态映射——自动检测
    安装了Node.js 从VScode 使用node -v 和 npm -v等命令却无效
  • 原文地址:https://www.cnblogs.com/rbzz/p/10029922.html
Copyright © 2020-2023  润新知