我正在将netMsmqBinding与事务性队列一起使用,尽管调用WCF服务没有问题,但是在处理完消息后60秒,该服务抛出了MsmqException。

这是例外:


System.ServiceModel.MsmqException(0xC00E0051):从队列接收消息时发生错误:无法识别的错误
-1072824239(0xc00e0051)。确保已安装并正在运行MSMQ。确保队列可供接收。在
System.ServiceModel.Channels.MsmqInputChannelBase.TryReceive(TimeSpan
超时,消息和消息)
System.ServiceModel.Dispatcher.InputChannelBinder.TryReceive(TimeSpan
超时,RequestContext&requestContext)
System.ServiceModel.Dispatcher.ErrorHandlingReceiver.TryReceive(TimeSpan
超时,RequestContext和requestContext)


我进行了一些研究,调试和跟踪,发现当收到一条新消息时,打开了两个事务,第一个事务在服务执行后立即提交,但是第二个从不提交,因此在60秒,DTC放弃它并抛出MsmqException。
这是操作定义:

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void SomeOperation(SomeParameter parameter)
{
  // business logic
}


关于正在发生的事情有什么想法,我该如何解决?

更新:

配置:

<netMsmqBinding>
  <binding name="TransactionalMsmqBinding" exactlyOnce="true" deadLetterQueue="System" receiveErrorHandling="Move">
    <security mode="None"/>
  </binding>
</netMsmqBinding>
...
<service name="SomeNamespace.SomeService">
  <endpoint contract="SomeNamespace.ISomeService" bindingConfiguration="TransactionalMsmqBinding" binding="netMsmqBinding" address="net.msmq://localhost/private/services/someservice.svc">
  </endpoint>
  <endpoint contract="SomeNamespace.IAnotherService" bindingConfiguration="TransactionalMsmqBinding" binding="netMsmqBinding" address="net.msmq://localhost/private/services/anotherservice.svc">
  </endpoint>
</service>


服务实施:

[ExceptionShieldingBehavior(typeof(ArgumentValidationException), typeof(ValidationServiceException))]
[AuthorizationAndAuditBehaviour]
[ServiceBehavior(Namespace = GlobalConstants.ServiceContractNamespace)]
public class SomeService: ISomeService, IAnotherService
{
  [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
  public void SomeOperation(SomeParameter parameter)
  {
    // business logic
  }

  [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
  public void AnotherOperation(AnotherParameter parameter)
  {
    // business logic
  }
}


服务合同:

[ServiceContract(Namespace = GlobalConstants.ServiceContractNamespace)]
public interface ISomeService
{
  [OperationContract(IsOneWay = true)]
  void SomeOperation(SomeParameter parameter);
}

[ServiceContract(Namespace = GlobalConstants.ServiceContractNamespace)]
public interface IAnotherService
{
  [OperationContract(IsOneWay = true)]
  void AnotherOperation(AnotherParameter parameter);
}


完整行为:


客户端发送消息
服务已激活
DTC启动两个事务(我可以在DTC监视器和TransactionManager.DistributedTransactionStarted事件中看到它们)
操作完成后,第一笔交易完成
(MsmqException引发)60秒后,第二个事务中止
wcf主机(IIS)有时出现故障(我对automatically recover it有一些代码,显然在.net 4中此行为已更改)

如果主机已损坏并自动恢复,则所有内容将在下一条消息中再次发生
如果主机没有损坏,第二笔交易将不会在下一次启动,并且一切都会顺利进行:)。
如果我回收AppPool,问题会再次出现

最佳答案

我发现了问题。

当我使用两个不同的msmq端点公开同一服务时,出于某些奇怪的原因,SMSvcHost.exe进程两次激活同一端点。

我刚刚写了一篇有关解决方案的文章:http://blog.jorgef.net/2011/07/msmqexception.html

希望对您有所帮助。

乔治

07-26 09:36