• WCF的回调使用实例代码说明


    很多时候我们会遇到,信息及时推送通知的情况,例如:监控设备时及时推送状态、报警信息等,我们就可以用WCF的回调机制来实现,下面以一个监控设备名字为例,如果设备名字发生改变,服务器就马上推送消息给客户端:
    (一、)服务器端

    1、建一个控制台应用程序:CallbackContractWCF
    2、创建ISendMessage接口

    namespace CallbackContractWCF
    {
        [ServiceContract(CallbackContract = typeof(IMessageCallbackContract))]
       public interface ISendMessage
        {
            /// 
            /// 保存客户端回调的实例
            /// 
            [OperationContract]
            void Subscribe();
        }
    }

    3、创建用于推送消息回调的接口IMessageCallbackContract

    namespace CallbackContractWCF
    {
       public interface IMessageCallbackContract
        {
            [OperationContract(IsOneWay = true)]
            void ReportMes(string responseToGreeting);
        }
    }

    4、创建实现接口ISendMessage的类SendMessage

     1 namespace CallbackContractWCF
     2 {
     3     [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,ConcurrencyMode=ConcurrencyMode.Multiple,UseSynchronizationContext=false)]
     4     public class SendMessage:ISendMessage
     5     {
     6         private System.Timers.Timer _setValueTimer;
     7         private IMessageCallbackContract callerProxy = null;
     8         ~SendMessage()
     9         {
    10             _setValueTimer.Stop();
    11             Device.OnChange -= new Action(Student_OnChange);
    12         }
    13         public SendMessage()
    14         {
    15             Thread.Sleep(3000);
    16             _setValueTimer = new System.Timers.Timer();
    17             _setValueTimer.AutoReset = true;
    18             _setValueTimer.Elapsed += Timer_Elapsed;
    19             _setValueTimer.Interval = 10000;
    20             _setValueTimer.Start();
    21             Device.OnChange += new Action(Student_OnChange);
    22         }
    23         //保存客户端回调的实例
    24         public void Subscribe()
    25         {
    26             try
    27             {
    28                 //获取当前调用的核心服务端实例的通道
    29                 callerProxy = OperationContext.Current.GetCallbackChannel();
    30             }
    31             catch (Exception ex)
    32             {
    33                 throw new FaultException(ex.Message);
    34             }
    35         }    
    36         private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    37         {
    38             Random rand = new Random();
    39             string name = "路由器"+rand.Next(10);
    40             SetName(name);
    41         }  
    42         private void SetName(string greeting)
    43         {
    44             if (greeting != Device.Name)
    45             {
    46                 Device.Name = greeting;
    47                 Device.Change(greeting);
    48             } 
    49         }  
    50         void Student_OnChange(string name)
    51         {
    52             try
    53             {
    54                 Console.Write("只要名字与当前的不同就向客户端推送通知
    ");
    55                 callerProxy.ReportMes(name);                    
    56             }
    57             catch (Exception ex)
    58             {
    59                 Console.Write(ex.Message);
    60             }
    61         }
    62     }
    63     //创建设备类
    64     public static class Device
    65     {
    66         public static string Name { get; set; }
    67         public static event Action OnChange;
    68         public static void Change(string name)
    69         {
    70             if (OnChange != null)
    71             {
    72                 OnChange.Invoke(name);
    73             }
    74         }
    75     }
    76 }
    View Code

    5、添加配置文件App.config

    <configuration>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="behavior1">
              <serviceMetadata httpGetEnabled="false"  />
              <serviceDebug includeExceptionDetailInFaults="false"  />
            </behavior>
          </serviceBehaviors>
        </behaviors>
        
        <bindings>
          <netTcpBinding>
            <binding name="BigBinding" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00"
                       sendTimeout="00:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
                       hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288000"
                       maxBufferSize="65536000" maxConnections="10" maxReceivedMessageSize="65536000">
    
              <readerQuotas maxDepth="32000" maxStringContentLength="8192000"
                            maxArrayLength="16384000" maxBytesPerRead="4096000"
                            maxNameTableCharCount="16384000"/>
              <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
              <security mode="None"/>
            </binding>
            <binding name="netTcpBinding_ISendMessage">
              <security mode="None"></security>
            </binding>
          </netTcpBinding>
        </bindings>
        
        <services>
          <service name="CallbackContractWCF.SendMessage" behaviorConfiguration="behavior1">
            <endpoint address="SendMessage"  binding="netTcpBinding" bindingConfiguration="BigBinding"  
                                contract="CallbackContractWCF.ISendMessage" name="netTcpBinding_ISendMessage" >
              <identity>
                <dns value="localhost" />
              </identity>
            </endpoint>
            <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
            <host>
              <baseAddresses>
                <add baseAddress="net.tcp://localhost:8729/Design_Time_Addresses/CallbackContractWCF/SendMessage/" />
              </baseAddresses>
            </host>
          </service>
        </services>
      </system.serviceModel>
    </configuration>
    View Code

    (二、)客户端
    1、创建控制台应用程序CallbackContractClient
    2、启动服务器,添加服务引用
    3、创建一个实现服务器端回调接口的类MessageCallback

    namespace CallbackContractClient
    {
        [System.ServiceModel.CallbackBehavior(IncludeExceptionDetailInFaults = true, UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
        public class MessageCallback : ISendMessageCallback
        {
            public event Action OnReportMes;
            
            //实现服务端的回调
            public void ReportMes(string responseMes)
            {
                if (OnReportMes != null)
                {
                    OnReportMes.Invoke(responseMes);
                }
            }
        }
    }

    4、在控制台主程序Program.cs中挂载服务

    namespace CallbackContractClient
    {
        class Program
        {
            static void Main(string[] args)
            {
                MessageCallback callback=new MessageCallback ();
                callback.OnReportMes+=new Action(callback_OnReportMes);
                InstanceContext content = new InstanceContext(callback);
                SendMessageClient clicent = new SendMessageClient(content);
                clicent.Subscribe();
    
                Console.Write("监控设备");
                Console.ReadLine();
            }    
    
            public static void callback_OnReportMes(string res)
            {
                Console.Write("
    设备的名称为:" + res);
                Console.ReadLine();
            }
        }
    }

    (三、)监测结果

  • 相关阅读:
    C# 如何定义让PropertyGrid控件显示[...]按钮,并且点击后以下拉框形式显示自定义控件编辑属性值
    “Word自动更改后的内容保存到通用文档模板上。是否加载该模板?“的解决办法
    Web服务器之iis,apache,tomcat三者之间的比较
    [转]C#如何把文件夹压缩打包然后下载
    [转]C#压缩打包文件
    C#——Marshal.StructureToPtr方法简介
    [Android Pro] 内容提供者ContentProvider的基本使用
    [Linux] awk命令详解
    [Linux] AWK命令详解(大全)
    [Android UI] ProgressBar自定义
  • 原文地址:https://www.cnblogs.com/huhangfei/p/4991814.html
Copyright © 2020-2023  润新知