此可变示例示例演示如何通过消息队列 (MSMQ) 传输来执行可变排队通信。 此示例使用 NetMsmqBinding。 此例中的服务是自承载控制台应用程序,通过它可以观察服务接收排队消息。
注释
本示例的设置过程和生成说明位于本主题末尾。
在排队通信中,客户端使用队列与服务通信。 更确切地说,客户端将消息发送到队列。 服务从队列接收消息。 因此,服务与客户端不必同时运行,才能使用队列进行通信。
发送不含保证的消息时,MSMQ 只会尽最大努力传递消息,这与确保仅传递一次的保证机制不同,该机制确保消息要么被传递,要么在无法传递时通知您消息无法传递。
在某些情况下,当及时传递比丢失消息更重要时,你可能希望通过队列发送没有保证的易失性消息。 可变消息在队列管理器崩溃后无法幸存。 因此,如果队列管理器崩溃,用于存储易失性消息的非事务性队列会幸存下来,但消息本身不会因为消息未存储在磁盘上。
注释
不能使用 MSMQ 在某个事务范围内发送没有保证的可变消息。 还必须创建非事务性队列以发送可变消息。
此示例中的服务协定是定义最适合与队列一起使用的单向服务的 IStockTicker。
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface IStockTicker
{
    [OperationContract(IsOneWay = true)]
    void StockTick(string symbol, float price);
}
服务操作显示股票代码和价格,如下示例代码所示:
public class StockTickerService : IStockTicker
{
    public void StockTick(string symbol, float price)
    {
        Console.WriteLine("Stock Tick {0}:{1} ", symbol, price);
     }
     …
}
该服务是自托管的。 使用 MSMQ 传输时,必须提前创建使用的队列。 这可以手动或通过代码完成。 在此示例中,服务包含用于检查队列是否存在的代码,并根据需要创建它。 队列名称从配置文件中读取。 ServiceModel 元数据实用工具工具(Svcutil.exe)使用基址为服务生成代理。
// Host the service within this EXE console application.
public static void Main()
{
    // Get MSMQ queue name from app settings in configuration.
    string queueName = ConfigurationManager.AppSettings["queueName"];
    // Create the transacted MSMQ queue if necessary.
    if (!MessageQueue.Exists(queueName))
        MessageQueue.Create(queueName);
    // Create a ServiceHost for the StockTickerService type.
    using (ServiceHost serviceHost = new ServiceHost(typeof(StockTickerService)))
    {
        // Open the ServiceHost to create listeners and start listening for messages.
        serviceHost.Open();
        // The service can now be accessed.
        Console.WriteLine("The service is ready.");
        Console.WriteLine("Press <ENTER> to terminate service.");
        Console.WriteLine();
        Console.ReadLine();
        // Close the ServiceHost to shutdown the service.
        serviceHost.Close();
    }
}
MSMQ 队列名称是在配置文件的 appSettings 部分中指定的。 服务的终结点在配置文件的 system.serviceModel 节中定义,并指定 netMsmqBinding 绑定。
注释
队列名称对本地计算机使用圆点 (.),并在使用 System.Messaging 创建队列时在其路径中使用反斜杠分隔符。 Windows Communication Foundation (WCF) 终结点地址指定一个 net.msmq: 方案,使用“localhost”来表示本地计算机,并在其路径中使用正斜杠。
配置中还指定了消息的保证和持久性或波动性。
<appSettings>
  <!-- use appSetting to configure MSMQ queue name -->
  <add key="queueName" value=".\private$\ServiceModelSamplesVolatile" />
</appSettings>
<system.serviceModel>
  <services>
    <service name="Microsoft.ServiceModel.Samples.StockTickerService"
             behaviorConfiguration="CalculatorServiceBehavior">
    ...
      <!-- Define NetMsmqEndpoint -->
      <endpoint address="net.msmq://localhost/private/ServiceModelSamplesVolatile"
                binding="netMsmqBinding"
                bindingConfiguration="volatileBinding"
                contract="Microsoft.ServiceModel.Samples.IStockTicker" />
    ...
    </service>
  </services>
  <bindings>
    <netMsmqBinding>
      <binding name="volatileBinding"
             durable="false"
           exactlyOnce="false"/>
    </netMsmqBinding>
  </bindings>
  ...
</system.serviceModel>
由于该示例通过使用非事务性队列来发送排队消息,因此无法将经过事务处理的消息发送到队列。
// Create a client.
Random r = new Random(137);
StockTickerClient client = new StockTickerClient();
float price = 43.23F;
for (int i = 0; i < 10; i++)
{
    float increment = 0.01f * (r.Next(10));
    client.StockTick("zzz" + i, price + increment);
}
//Closing the client gracefully cleans up resources.
client.Close();
运行示例时,客户端和服务活动会显示在服务和客户端控制台窗口中。 可以看到服务从客户端接收消息。 在每个控制台窗口中按 Enter 可以关闭服务和客户端。 请注意:由于正在使用队列,因此不必同时启动和运行客户端和服务。 即使关闭客户端再启动服务,仍然可以接收到消息。
The service is ready.
Press <ENTER> to terminate service.
Stock Tick zzz0:43.25
Stock Tick zzz1:43.23
Stock Tick zzz2:43.28
Stock Tick zzz3:43.3
Stock Tick zzz4:43.23
Stock Tick zzz5:43.25
Stock Tick zzz6:43.25
Stock Tick zzz7:43.24
Stock Tick zzz8:43.32
Stock Tick zzz9:43.3
设置、生成和运行示例
- 确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。 
- 若要生成解决方案的 C# 或 Visual Basic .NET 版本,请按照 生成 Windows Communication Foundation 示例中的说明进行操作。 
- 若要在单台计算机或跨计算机配置中运行示例,请按照 运行 Windows Communication Foundation 示例中的说明进行操作。 
默认情况下使用 NetMsmqBinding 启用传输安全。 MSMQ 传输安全性有两个相关属性, MsmqAuthenticationModeMsmqProtectionLevel.默认情况下,身份验证模式设置为Windows,保护级别设置为 。Sign 要使 MSMQ 提供身份验证和签名功能,它必须是域的一部分,并且必须安装 MSMQ 的 Active Directory 集成选项。 如果在不符合这些条件的计算机上运行此示例,则会收到错误。
在加入到工作组或在没有 Active Directory 集成的计算机上运行示例
- 如果计算机不是域的一部分,或者未安装 Active Directory 集成,请将身份验证模式和保护级别设置为 - None关闭传输安全性,如以下示例配置代码所示:- <system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.StockTickerService" behaviorConfiguration="StockTickerServiceBehavior"> <host> <baseAddresses> <add baseAddress="http://localhost:8000/ServiceModelSamples/service"/> </baseAddresses> </host> <!-- Define NetMsmqEndpoint --> <endpoint address="net.msmq://localhost/private/ServiceModelSamplesVolatile" binding="netMsmqBinding" bindingConfiguration="volatileBinding" contract="Microsoft.ServiceModel.Samples.IStockTicker" /> <!-- the mex endpoint is exposed at http://localhost:8000/ServiceModelSamples/service/mex --> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <bindings> <netMsmqBinding> <binding name="volatileBinding" durable="false" exactlyOnce="false"> <security mode="None" /> </binding> </netMsmqBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="StockTickerServiceBehavior"> <serviceMetadata httpGetEnabled="True"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
- 在运行示例之前,请确保在服务器和客户端上更改配置。 - 注释 - 将 - security mode设置为- None等同于将MsmqAuthenticationMode、MsmqProtectionLevel和- Message的安全性设置为- None。