消息隊(duì)列不同于傳統(tǒng)的請(qǐng)求響應(yīng)模式,它是客戶端把消息發(fā)送給請(qǐng)求消息隊(duì)列,服務(wù)可以稍后對(duì)消息進(jìn)行處理并把處理結(jié)果發(fā)送給響應(yīng)隊(duì)列,而后客戶端從響應(yīng)隊(duì)列讀取服務(wù)處理后的消息。而且使用消息隊(duì)列可以使客戶端實(shí)現(xiàn)脫機(jī)工作。脫機(jī)應(yīng)用程序必須有本地緩存數(shù)據(jù),要采用異步通訊而且要把消息持久化,在與服務(wù)器聯(lián)機(jī)后將消息發(fā)送出去。WCF是使用NetMsmqBinding來(lái)支持消息隊(duì)列的,傳輸消息不是通過(guò)TCP或HTTP等,而是通過(guò)微軟消息隊(duì)列(MSMQ),這是Windows組件,可以通過(guò)1)控制面板2)程序和功能:打開(kāi)或關(guān)閉Windows功能3)出現(xiàn)如下界面,點(diǎn)確定即可安裝。
安裝成功后可以右擊我的電腦選擇管理而后會(huì)有如下界面:
理論也不說(shuō)那么多了,MSDN上說(shuō)的很詳細(xì),還是寫(xiě)些相對(duì)簡(jiǎn)單清晰的代碼的整體上把握下消息隊(duì)列,有時(shí)候看書(shū)不是太明白的地方,調(diào)試下代碼或許會(huì)有種豁然開(kāi)朗的感覺(jué)。因?yàn)橐S護(hù)服務(wù)端和客戶端雙向通訊,所以需要兩個(gè)隊(duì)列,兩個(gè)單向操作契約。而客戶端的功能既要發(fā)送消息到請(qǐng)求消息隊(duì)列又要從響應(yīng)消息隊(duì)列讀取響應(yīng)消息,服務(wù)端則需要從調(diào)用隊(duì)列讀取消息進(jìn)行處理,處理后發(fā)送的響應(yīng)消息隊(duì)列。實(shí)際上客戶端和服務(wù)端并沒(méi)有直接通訊,而是通過(guò)兩個(gè)隊(duì)列來(lái)進(jìn)行通訊的。
請(qǐng)求契約:
using System;
using System.ServiceModel;
namespace IFruit
{
[ServiceContract]
public interface IFruitService
{
[OperationContract(IsOneWay = true )]
void GetFruitInfo( string fruitName, string price);
}
}
請(qǐng)求服務(wù)實(shí)現(xiàn):
using System;
using System.Messaging;
using System.ServiceModel;
using IFruit;
using IFruitResponse;
namespace FruitSvc
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class FruitService:IFruitService
{
[OperationBehavior(TransactionScopeRequired = true )]
public void GetFruitInfo( string fruitName, string price)
{
string info = string .Empty;
ExceptionDetail error = null ;
try
{
info = string .Format( " The Fruit Name Is {0} And Price Is {1} " , fruitName, price);
}
catch (Exception ex)
{
error = new ExceptionDetail(ex);
}
finally
{
// 創(chuàng)建隊(duì)列
string queueName = " .\\private$\\FruitResponseQueue " ;
if ( ! MessageQueue.Exists(queueName))
{
MessageQueue.Create(queueName, true );
}
// 把處理后的消息放到響應(yīng)消息隊(duì)列
EndpointAddress address = new EndpointAddress( " net.msmq://localhost/private/FruitResponseQueue " );
NetMsmqBinding binding = new NetMsmqBinding();
binding.Security.Mode = NetMsmqSecurityMode.None;
using (ChannelFactory < IFruitResponseService > factory = new ChannelFactory < IFruitResponseService > (binding,
address))
{
IFruitResponseService response = factory.CreateChannel();
response.OnGetFruitInfoCompleted(info, error);
}
}
}
}
}
響應(yīng)契約:
using System;
using System.ServiceModel;
namespace IFruitResponse
{
[ServiceContract]
public interface IFruitResponseService
{
[OperationContract(IsOneWay = true )]
void OnGetFruitInfoCompleted( string fruitInfo, ExceptionDetail error);
}
}
響應(yīng)服務(wù)實(shí)現(xiàn):
using System;
using System.Collections.Generic;
using System.ServiceModel;
using IFruitResponse;
namespace FruitResponse
{
// 定義一泛型委托
public delegate void GenericEventHandler < T > (T t);
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class FruitResponseService : IFruitResponseService
{
// 聲明并初始化一委托事件
public static event GenericEventHandler < string > GetFruitInfoCompleted = delegate { };
[OperationBehavior(TransactionScopeRequired = true )]
public void OnGetFruitInfoCompleted( string fruitInfo, ExceptionDetail error)
{
if (error == null )
{
GetFruitInfoCompleted(fruitInfo);
}
}
}
}
客戶端服務(wù)寄存:
using System;
using System.ServiceModel;
using System.Messaging;
using FruitResponse;
using IFruit;
namespace FruitClientHost
{
class Program
{
static void Main( string [] args)
{
// GetFruitInfoCompleted發(fā)生后調(diào)用OnGetFruitInfoCompleted方法
FruitResponseService.GetFruitInfoCompleted += Program.OnGetFruitInfoCompleted;
// 創(chuàng)建兩個(gè)隊(duì)列
string queueName = " .\\private$\\GetFruitInfoQueue " ;
if ( ! MessageQueue.Exists(queueName))
{
MessageQueue.Create(queueName, true );
}
string queueName1 = " .\\private$\\FruitResponseQueue " ;
if ( ! MessageQueue.Exists(queueName1))
{
MessageQueue.Create(queueName1, true );
}
// 接收響應(yīng)消息
ServiceHost fruitHost = new ServiceHost( typeof (FruitResponseService),
new Uri( " net.msmq://localhost/private/FruitResponseQueue " ));
NetMsmqBinding netMsmqBind = new NetMsmqBinding();
netMsmqBind.Security.Mode = NetMsmqSecurityMode.None;
fruitHost.AddServiceEndpoint( typeof (IFruitResponse.IFruitResponseService), netMsmqBind, "" );
fruitHost.Open();
// 發(fā)送請(qǐng)求消息到請(qǐng)求隊(duì)列
EndpointAddress address = new EndpointAddress( " net.msmq://localhost/private/GetFruitInfoQueue " );
NetMsmqBinding binding = new NetMsmqBinding();
binding.Security.Mode = NetMsmqSecurityMode.None;
using (ChannelFactory < IFruitService > factory = new ChannelFactory < IFruitService > (binding, address))
{
IFruitService fruit = factory.CreateChannel();
fruit.GetFruitInfo( " banana " , " 6.00 " );
}
Console.WriteLine( " The Client Is Running ... " );
Console.ReadLine();
fruitHost.Close();
}
static void OnGetFruitInfoCompleted( string fruitInfo)
{
Console.WriteLine(fruitInfo);
}
}
}
服務(wù)端服務(wù)寄存:
using System;
using System.ServiceModel;
using FruitSvc;
using IFruit;
namespace FruitResponseHost
{
class Program
{
static void Main( string [] args)
{
ServiceHost fruitServiceHost = new ServiceHost( typeof (FruitService),
new Uri( " net.msmq://localhost/private/GetFruitInfoQueue " ));
NetMsmqBinding netMsmqBind = new NetMsmqBinding();
netMsmqBind.Security.Mode = NetMsmqSecurityMode.None;
fruitServiceHost.AddServiceEndpoint( typeof (IFruitService), netMsmqBind, "" );
fruitServiceHost.Open();
Console.WriteLine( " The Service Is Running ... " );
Console.ReadLine();
fruitServiceHost.Close();
}
}
}
運(yùn)行程序,先啟動(dòng)客戶端,此時(shí)的消息可以通過(guò)MSMQ管理控制臺(tái)進(jìn)行管理:
從管理控制臺(tái)可以看出GetFruitInfoQueue有一條消息,而后啟動(dòng)服務(wù)端:
客戶端已經(jīng)呈現(xiàn)出服務(wù)處理后的消息信息,GetFruitInfoQueue的消息已經(jīng)被服務(wù)處理了,消息數(shù)目變?yōu)?。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
