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("只要名字与当前的不同就向客户端推送通知\r\n");
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("\r\n设备的名称为:" + res);
            Console.ReadLine();
        }
    }
}

(三、)监测结果

posted @ 2015-11-24 15:43  Mr. Hu  阅读(625)  评论(0编辑  收藏  举报
Map