zoukankan      html  css  js  c++  java
  • 利用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类,基本上我也弄不太明白,反正就这么写也不出错,但不写肯定是错<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中加入了服务端向客户端广播的一些代码

  • 相关阅读:
    php多态
    ssl certificate problem: self signed certificate in certificate chain
    test plugin
    open specific port on ubuntu
    junit vs testng
    jersey rest service
    toast master
    use curl to test java webservice
    update folder access
    elk
  • 原文地址:https://www.cnblogs.com/weifeng123/p/11038697.html
Copyright © 2011-2022 走看看