zoukankan      html  css  js  c++  java
  • 【SignalR学习系列】5. SignalR WPF程序

    首先创建 WPF Server 端,新建一个 WPF 项目

    安装 Nuget 包

    替换 MainWindows 的Xaml代码

    <Window x:Class="WPFServer.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="WPF SignalR Server" Height="319" Width="343  ">
        <Grid>
    
            <Button x:Name="ButtonStart" Content="Start" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="100" Click="ButtonStart_Click"/>
            <Button x:Name="ButtonStop" Content="Stop" HorizontalAlignment="Left" Margin="225,10,0,0" VerticalAlignment="Top" Width="100" Click="ButtonStop_Click" IsEnabled="False"/>
            <RichTextBox x:Name="RichTextBoxConsole" HorizontalAlignment="Left" Height="243" Margin="10,35,0,0" VerticalAlignment="Top" Width="315">
                <FlowDocument>
                    <Paragraph>
                    </Paragraph>
                </FlowDocument>
            </RichTextBox>
    
        </Grid>
    </Window>

    替换 MainWindows 后台代码

    using Microsoft.AspNet.SignalR;
    using Microsoft.Owin.Cors;
    using Microsoft.Owin.Hosting;
    using Owin;
    using System;
    using System.Reflection;
    using System.Threading.Tasks;
    using System.Windows;
    
    namespace WPFServer
    {
        /// <summary>
        /// WPF host for a SignalR server. The host can stop and start the SignalR
        /// server, report errors when trying to start the server on a URI where a
        /// server is already being hosted, and monitor when clients connect and disconnect. 
        /// The hub used in this server is a simple echo service, and has the same 
        /// functionality as the other hubs in the SignalR Getting Started tutorials.
        /// For simplicity, MVVM will not be used for this sample.
        /// </summary>
        public partial class MainWindow : Window
        {
            public IDisposable SignalR { get; set; }
            const string ServerURI = "http://localhost:8080";
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
            /// <summary>
            /// Calls the StartServer method with Task.Run to not
            /// block the UI thread. 
            /// </summary>
            private void ButtonStart_Click(object sender, RoutedEventArgs e)
            {
                WriteToConsole("Starting server...");
                ButtonStart.IsEnabled = false;
                Task.Run(() => StartServer());
            }
    
            /// <summary>
            /// Stops the server and closes the form. Restart functionality omitted
            /// for clarity.
            /// </summary>
            private void ButtonStop_Click(object sender, RoutedEventArgs e)
            {
                SignalR.Dispose();
                Close();
            }
    
            /// <summary>
            /// Starts the server and checks for error thrown when another server is already 
            /// running. This method is called asynchronously from Button_Start.
            /// </summary>
            private void StartServer()
            {
                try
                {
                    SignalR = WebApp.Start(ServerURI);
                }
                catch (TargetInvocationException)
                {
                    WriteToConsole("A server is already running at " + ServerURI);
                    this.Dispatcher.Invoke(() => ButtonStart.IsEnabled = true);
                    return;
                }
                this.Dispatcher.Invoke(() => ButtonStop.IsEnabled = true);
                WriteToConsole("Server started at " + ServerURI);
            }
            ///This method adds a line to the RichTextBoxConsole control, using Dispatcher.Invoke if used
            /// from a SignalR hub thread rather than the UI thread.
            public void WriteToConsole(String message)
            {
                if (!(RichTextBoxConsole.CheckAccess()))
                {
                    this.Dispatcher.Invoke(() =>
                        WriteToConsole(message)
                    );
                    return;
                }
                RichTextBoxConsole.AppendText(message + "
    ");
            }
        }
        /// <summary>
        /// Used by OWIN's startup process. 
        /// </summary>
        class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                app.UseCors(CorsOptions.AllowAll);
                app.MapSignalR();
            }
        }
        /// <summary>
        /// Echoes messages sent using the Send message by calling the
        /// addMessage method on the client. Also reports to the console
        /// when clients connect and disconnect.
        /// </summary>
        public class MyHub : Hub
        {
            public void Send(string name, string message)
            {
                Clients.All.addMessage(name, message);
                //Groups.Add
            }
            public override Task OnConnected()
            {
                //Use Application.Current.Dispatcher to access UI thread from outside the MainWindow class
                Application.Current.Dispatcher.Invoke(() =>
                    ((MainWindow)Application.Current.MainWindow).WriteToConsole("Client connected: " + Context.ConnectionId));
    
                return base.OnConnected();
            }
            public override Task OnDisconnected(bool ss)
            {
                //Use Application.Current.Dispatcher to access UI thread from outside the MainWindow class
                Application.Current.Dispatcher.Invoke(() =>
                    ((MainWindow)Application.Current.MainWindow).WriteToConsole("Client disconnected: " + Context.ConnectionId));
    
                return base.OnDisconnected(ss);
            }
        }
    }

     创建 WPF Client 端,新建一个 WPF 项目

     

    安装 Nuget 包

     

    替换 MainWindow 的前台 xmal 文件

    <Window x:Name="WPFClient" x:Class="WPFClient.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="WPF SignalR Client" Height="552" Width="517" MinWidth="517" MinHeight="552" ResizeMode="CanMinimize" Closing="WPFClient_Closing">
        <Grid>
            <StackPanel x:Name="SignInPanel" Margin="10,0" MaxWidth="550">
                <Label Content="Enter user name:"/>
                <Grid>
                    <TextBox x:Name="UserNameTextBox" Height="20" Margin="0,0,80,0"/>
                    <Button x:Name="SignInButton" Content="Sign In" Width="75" Click="SignInButton_Click" HorizontalAlignment="Right"/>
                </Grid>
    
                <Label x:Name="StatusText" Visibility="Collapsed" HorizontalAlignment="Center" Margin="0,10"/>
            </StackPanel>
            <StackPanel x:Name="ChatPanel" Margin="10" MaxWidth="550" Visibility="Collapsed">
                <Grid>
                    <TextBox x:Name="TextBoxMessage" Height="20" TextWrapping="Wrap" Margin="0,0,80,0"/>
                    <Button x:Name="ButtonSend" Content="Send" Width="75" Height="20" Click="ButtonSend_Click" IsDefault="True" IsEnabled="False" HorizontalAlignment="Right"/>
                </Grid>
                <RichTextBox x:Name="RichTextBoxConsole" HorizontalAlignment="Left" Height="461" ScrollViewer.VerticalScrollBarVisibility="Auto" Margin="0,10" IsReadOnly="True"/>
            </StackPanel>
        </Grid>
    </Window>

    替换后台代码

    using System;
    using System.Net.Http;
    using System.Windows;
    using Microsoft.AspNet.SignalR.Client;
    
    namespace WPFClient
    {
        /// <summary>
        /// SignalR client hosted in a WPF application. The client
        /// lets the user pick a user name, connect to the server asynchronously
        /// to not block the UI thread, and send chat messages to all connected 
        /// clients whether they are hosted in WinForms, WPF, or a web application.
        /// For simplicity, MVVM will not be used for this sample.
        /// </summary>
        public partial class MainWindow : Window
        {
            /// <summary>
            /// This name is simply added to sent messages to identify the user; this 
            /// sample does not include authentication.
            /// </summary>
            public String UserName { get; set; }
            public IHubProxy HubProxy { get; set; }
            const string ServerURI = "http://localhost:8080/signalr";
            public HubConnection Connection { get; set; }
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void ButtonSend_Click(object sender, RoutedEventArgs e)
            {
                HubProxy.Invoke("Send", UserName, TextBoxMessage.Text);
                TextBoxMessage.Text = String.Empty;
                TextBoxMessage.Focus();
            }
    
            /// <summary>
            /// Creates and connects the hub connection and hub proxy. This method
            /// is called asynchronously from SignInButton_Click.
            /// </summary>
            private async void ConnectAsync()
            {
                Connection = new HubConnection(ServerURI);
                Connection.Closed += Connection_Closed;
                HubProxy = Connection.CreateHubProxy("MyHub");
                //Handle incoming event from server: use Invoke to write to console from SignalR's thread
                HubProxy.On<string, string>("AddMessage", (name, message) =>
                    this.Dispatcher.Invoke(() =>
                        RichTextBoxConsole.AppendText(String.Format("{0}: {1}
    ", name, message))
                    )
                );
                try
                {
                    await Connection.Start();
                }
                catch (HttpRequestException)
                {
                    StatusText.Content = "Unable to connect to server: Start server before connecting clients.";
                    //No connection: Don't enable Send button or show chat UI
                    return;
                }
    
                //Show chat UI; hide login UI
                SignInPanel.Visibility = Visibility.Collapsed;
                ChatPanel.Visibility = Visibility.Visible;
                ButtonSend.IsEnabled = true;
                TextBoxMessage.Focus();
                RichTextBoxConsole.AppendText("Connected to server at " + ServerURI + "
    ");
            }
    
            /// <summary>
            /// If the server is stopped, the connection will time out after 30 seconds (default), and the 
            /// Closed event will fire.
            /// </summary>
            void Connection_Closed()
            {
                //Hide chat UI; show login UI
                var dispatcher = Application.Current.Dispatcher;
                dispatcher.Invoke(() => ChatPanel.Visibility = Visibility.Collapsed);
                dispatcher.Invoke(() => ButtonSend.IsEnabled = false);
                dispatcher.Invoke(() => StatusText.Content = "You have been disconnected.");
                dispatcher.Invoke(() => SignInPanel.Visibility = Visibility.Visible);
            }
    
            private void SignInButton_Click(object sender, RoutedEventArgs e)
            {
                UserName = UserNameTextBox.Text;
                //Connect to server (use async method to avoid blocking UI thread)
                if (!String.IsNullOrEmpty(UserName))
                {
                    StatusText.Visibility = Visibility.Visible;
                    StatusText.Content = "Connecting to server...";
                    ConnectAsync();
                }
            }
    
            private void WPFClient_Closing(object sender, System.ComponentModel.CancelEventArgs e)
            {
                if (Connection != null)
                {
                    Connection.Stop();
                    Connection.Dispose();
                }
            }
        }
    }

    在解决方案的属性里面,设置 Server 和 Client 端一起启动

    运行查看效果

    源代码链接:

    链接: http://pan.baidu.com/s/1eRC2qVw 密码: twh3

  • 相关阅读:
    pytorch的函数中的group参数的作用
    pytorch的函数中的dilation参数的作用
    resnet18全连接层改成卷积层
    Pytorch实现UNet例子学习
    MyEclipse中出现Address already in use:JVM_Bind:8080
    为SQL数据库创建登录名和密码
    集合体系
    排序算法及其java实现
    java泛型通配符?
    Arrays.asList的用法
  • 原文地址:https://www.cnblogs.com/Soulless/p/7234352.html
Copyright © 2011-2022 走看看