先看運行效果:在網頁中發送消息【如圖】,利用WCF的Duplex服務向Winform 程序推送消息,Winform端接收到消息,
先建立兩個項目,一個WebForm 項目和一個WinForm項目,並在項目下 建立好各自需要的文件
SendMessage.aspx 是發送消息的Web頁面
ISendMessageService.cs 和 SendMessageService.svc用來實現WCF的 Duplex服務
GetMessageForm.cs 是接收消息的Winform窗口
當然, 還需要建立一個消息實體文件:MessageEntity.cs,為簡單起見,只給他定義一個 屬性。
[DataContract]
public class MessageEntity
{
[DataMember]
public string Content { get; set; }
}
基本原理是消息發送的頁面將要發送的消息列表保存在全局緩存 中,在WCF的Duplex服務中取得要發送的消息推送到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 用來實現將緩存中的消息列表一個一個的推送出 去,采用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<ISendMessageServiceCallB ack>();
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服務已創建,拷貝該服務的地址,例如在我本機上 是:http://localhost:1407/SendMessageService.svc,並在WinApp項目中增加 該服務的引用
GetMessageForm.cs 實現如下:
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
}