C# 从MSMQ中删除多条消息

C# 从MSMQ中删除多条消息,c#,wcf,msmq,msmq-wcf,C#,Wcf,Msmq,Msmq Wcf,我有一个运行在WCF和MSMQ上的特定服务。 一切正常,但我们有一个要求,即如果在处理一个作业过程中发生意外情况,则不应影响任何其他作业。 该服务设计为健壮的,并且是可靠的。我们在两年的运营中从未发生过it崩溃,但最近我们的客户喜欢终止服务流程,并抱怨失去了不止一份工作 为了进行调查,我添加了一个计时器,它每200毫秒跟踪一次队列的内容,并发现了一些意外情况。 处理请求时,WCF会从队列中删除多条消息。 以下是相关事件的smartinspec跟踪(中间列中的数字是线程ID): 它似乎总是将一条

我有一个运行在WCF和MSMQ上的特定服务。 一切正常,但我们有一个要求,即如果在处理一个作业过程中发生意外情况,则不应影响任何其他作业。 该服务设计为健壮的,并且是可靠的。我们在两年的运营中从未发生过it崩溃,但最近我们的客户喜欢终止服务流程,并抱怨失去了不止一份工作

为了进行调查,我添加了一个计时器,它每200毫秒跟踪一次队列的内容,并发现了一些意外情况。 处理请求时,WCF会从队列中删除多条消息。 以下是相关事件的smartinspec跟踪(中间列中的数字是线程ID):

它似乎总是将一条消息缓冲在服务过程中的某个地方。 我一直在查阅WCF文档,但没有找到任何关于这种行为的参考资料 我能做些什么来防止这种缓冲,或者你能让我参考一些相关的文章吗

以下是服务类:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
 public class TheService : ITheService
 {
   private readonly ITraceFacade trace = TraceFactory.Resolve();//for tracing

   public ClientCodeWrapper clientCodeWrapper { get; set; }// a wrapper for libraries written by our client. it's instantiated and set in the OnStart method of the service host class

   public void ProcessJob(long jobId)
   {
      using (this.trace.ActivityScope(string.Format(CultureInfo.InvariantCulture, "The Service.ProcessJob({0})", jobId)))
       {        
         this.clientCodeWrapper.ProcessJob(jobId);        
       }
    }    
 }
这是我的服务配置

<system.serviceModel>
  <bindings>
    <netMsmqBinding>
      <binding name="MsmqBindingNonTransactionalNoSecurity" exactlyOnce="false">
        <security mode="None"/>
      </binding>
    </netMsmqBinding>
  </bindings>

  <services>
    <service name="TheService">
      <host>
        <baseAddresses>
          <add baseAddress="http://localhost:8080/TheServiceIn"   />           
        </baseAddresses>
      </host>           
      <endpoint address="net.msmq://localhost/private/TheServiceIn"  
              binding="netMsmqBinding"
              bindingConfiguration="MsmqBindingNonTransactionalNoSecurity" 
              contract="ITheService">         
        <identity>
          <dns value="localhost"/>
        </identity>
      </endpoint>       

      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
  </services>
</system.serviceModel>

你所看到的似乎正是我所期待的。的确,WCF可以读取队列中的多条消息进行处理。通常,这不是问题,对于事务性队列,这肯定不是问题(因为每个事务只有在消息处理完成后才会提交,否则事务将中止并将消息返回到队列)

因此,基本上,您选择了通过禁用事务和使用非事务队列来避免消息丢失的方式来处理消息。基本上,您告诉MSMQ和WCF偶尔丢失消息是完全可以的


考虑一下如果你的机器(或MSMQservice)崩溃会发生什么:你不会只失去一份工作;您将丢失所有消息,因为消息不会被持久化。

同意,尽管启用事务性队列有一个缺点,即他的客户将无法停止服务以删除阻碍处理的消息。@TomRedfern我认为这不会是一个问题,但是谢谢你和我分享这个问题。我把这个标记为官方答案,因为跨国排队确实有效。但是,我们选择保持软件不变,因为事务作用域会干扰我们的sql事务。我以前遇到过这种行为。你对此无能为力。这就是netMsmqBinding堆栈的工作方式。