利用WCF的Duplex服務向Winform程序推送消息
先看運行效果:在網頁中發(fā)送消息【如圖】,利用WCF的Duplex服務向Winform程序推送消息,Winform端接收到消息,
先建立兩個項目,一個WebForm 項目和一個WinForm項目,并在項目下建立好各自需要的文件
SendMessage.aspx 是發(fā)送消息的Web頁面
ISendMessageService.cs 和 SendMessageService.svc用來實現(xiàn)WCF的Duplex服務
GetMessageForm.cs 是接收消息的Winform窗口
當然,還需要建立一個消息實體文件:MessageEntity.cs,為簡單起見,只給他定義一個屬性。
- [DataContract]
- public class MessageEntity
- {
- [DataMember]
- public string Content { get; set; }
- }
基本原理是消息發(fā)送的頁面將要發(fā)送的消息列表保存在全局緩存中,在WCF的Duplex服務中取得要發(fā)送的消息推送到Winform端,SendMessage.aspx的代碼如下:
- protected void btnSend_Click(object sender, EventArgs e)
- {
- MessageEntity message = new MessageEntity();
- message.Content = txtMessageContent.Text;
- List<MessageEntity> messageList = HttpRuntime.Cache["MessageEntityList"] as List<MessageEntity>;
- if (messageList == null)
- {
- messageList = new List<MessageEntity>();
- messageList.Add(message);
- HttpRuntime.Cache.Add("MessageEntityList", messageList, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Default, null);
- }
- else
- {
- messageList.Add(message);
- HttpRuntime.Cache["MessageEntityList"] = messageList;
- }
- lbCacheCount.Text = messageList.Count.ToString();
- }
- ISendMessageService.cs 用來定義消息接收接口和回調接口
- Code
- [ServiceContract(CallbackContract = typeof(ISendMessageServiceCallBack))]
- public interface ISendMessageService
- {
- [OperationContract(IsOneWay = true)]
- void GetMessage();
- }
- public interface ISendMessageServiceCallBack
- {
- [OperationContract(IsOneWay = true)]
- void ReceiveMessage(MessageEntity messageEntity);
- }
- SendMessageService.svc.cs 用來實現(xiàn)將緩存中的消息列表一個一個的推送出去,采用Timer類每2-5秒鐘推送一次:
- Code
- [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
- public class SendMessageService : ISendMessageService
- {
- ISendMessageServiceCallBack callback;
- Timer heartTimer;
- Random random = new Random();
- #region ISendMessageService 成員
- public void GetMessage()
- {
- callback = OperationContext.Current.GetCallbackChannel<ISendMessageServiceCallBack>();
- heartTimer = new Timer(new TimerCallback(heartTimer_Elapsed), null, 3000, Timeout.Infinite);
- }
- #endregion
- private void heartTimer_Elapsed(object data)
- {
- List<MessageEntity> messageList = HttpRuntime.Cache["MessageEntityList"] as List<MessageEntity>;
- if (messageList != null && messageList.Count > 0)
- {
- MessageEntity message = messageList[0];
- messageList.Remove(message);
- HttpRuntime.Cache["MessageEntityList"] = messageList;
- callback.ReceiveMessage(message);
- }
- int interval = random.Next(2000, 5000);
- heartTimer.Change(interval, Timeout.Infinite);
- }
- }
記得修改Web.Config中EndPoint Binding 為wsDualHttpBinding ,這樣才支持WCF的Duplex服務
- <service behaviorConfiguration="WebApp.SendMessageServiceBehavior" name="WebApp.SendMessageService">
- <endpoint address="" binding="wsDualHttpBinding" contract="WebApp.ISendMessageService">
- <identity>
- <dns value="localhost"/>
- </identity>
- </endpoint>
- <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
- </service>
WebApp項目的工作已經完成,若沒有錯誤可在瀏覽器中看到該WCF的Duplex服務已創(chuàng)建,拷貝該服務的地址,例如在我本機上是:http://localhost:1407/SendMessageService.svc,并在WinApp項目中增加該服務的引用
GetMessageForm.cs 實現(xiàn)如下:
- public partial class GetMessageForm : Form,ISendMessageServiceCallback
- {
- SendMessageServiceClient client;
- public GetMessageForm()
- {
- InitializeComponent();
- client = new SendMessageServiceClient(new System.ServiceModel.InstanceContext(this));
- }
- private void btnStartGet_Click(object sender, EventArgs e)
- {
- client.GetMessage();
- }
- private delegate void UpdateListBoxDelegate(string Message);
- private void UpdateListBox(string message)
- {
- this.listbMessage.Items.Add(message);
- listbMessage.SelectedIndex = listbMessage.Items.Count - 1;
- }
- #region ISendMessageServiceCallback 成員
- public void ReceiveMessage(MessageEntity messageEntity)
- {
- if (true == listbMessage.InvokeRequired)
- {
- listbMessage.Invoke(new UpdateListBoxDelegate(UpdateListBox), messageEntity.Content);
- }
- else
- {
- UpdateListBox(messageEntity.Content);
- }
- }
- #endregion
- }
【編輯推薦】