不同线程中的WCF事务

时间:2017-07-28 08:29:07

标签: vb.net multithreading wcf transactions

客户端应用程序在一个TransactionScope中调用WCF服务,希望在调用失败时回滚整个事务。应用程序&服务正常,但如果两个客户端同时向WCF服务发送请求,则其中一个客户端会出现死锁错误。

这是客户端应用程序中的代码:

 Using transcop As New TransactionScope(TransactionScopeOption.Required, New TransactionOptions() With {.IsolationLevel = IsolationLevel.Serializable})
        Try
            Dim test = LeaProS.RechnungenService.RechnungenInternalWSClient.FacadePdfVerarbeitungInternalWS.PdfVerarbeitungLoslegen(11928, True)

            transcop.Complete()

        Catch ex As Exception
            transcop.Dispose()
            Throw
        End Try
    End Using

Public Shared Function PdfVerarbeitungLoslegen(idAusGeplanteRechnungen As Integer, lettershopDrucken As Boolean) As Byte()

    Dim client As RechnungInternalWSClient = Nothing

    Try
        ' Verbindung zum Webservice initialiseren.
        client = New RechnungInternalWSClient("NetTcpBinding_IRechnungInternalWS")
        client.Open()

        ' verarbeitung starten
        Dim retval = client.PdfVerarbeitungLoslegen(idAusGeplanteRechnungen:=idAusGeplanteRechnungen, LettershopDrucken:=lettershopDrucken)
        client.Close()
        client = Nothing

        'PDF zurückgeben.
        Return retval.pdf

    Catch ex As Exception
        RechnungenUtils.ClientKontrolliertBeenden(client)
        Throw
    End Try

End Function

这是服务合同:

<ServiceBehavior(ConcurrencyMode:=ConcurrencyMode.Multiple,
InstanceContextMode:=InstanceContextMode.PerCall,
UseSynchronizationContext:=True,
TransactionIsolationLevel:=System.Transactions.IsolationLevel.Serializable,
TransactionTimeout:="00:00:30",
ReleaseServiceInstanceOnTransactionComplete:=False
)>
Public Class RechnungInternalWS
Implements IRechnungInternalWS

<OperationBehavior(TransactionScopeRequired:=True, 
TransactionAutoComplete:=True)>
Public Function PdfVerarbeitungLoslegen(idAusGeplanteRechnungen As Integer, 
LettershopDrucken As Boolean) As RechnungPDFOriginal Implements 
IRechnungInternalWS.PdfVerarbeitungLoslegen
' do something
End Function

这些是配置文件:

<endpoint address="net.tcp://eldienste:555/IRechnungInternalWS"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IRechnungInternalWS"
contract="ServiceReference.IRechnungInternalWS" name="NetTcpBinding_IRechnungInternalWS" />

<binding name="NetTcpBinding_IRechnungInternalWS" closeTimeout="00:01:00"
      openTimeout="00:01:00" receiveTimeout="00:01:00" sendTimeout="00:01:00"
      transactionFlow="True" transferMode="Buffered" transactionProtocol="OleTransactions"
      hostNameComparisonMode="StrongWildcard" listenBacklog="250"
      maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="250"
      maxReceivedMessageSize="65536">
  <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="2147483646"
      maxBytesPerRead="4096" maxNameTableCharCount="16384" />
  <reliableSession ordered="true" inactivityTimeout="00:10:00"
      enabled="false" />
  <security mode="None">
    <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
    <message clientCredentialType="Windows" />
  </security>
</binding>

我做错了什么?

2 个答案:

答案 0 :(得分:1)

我找到了正确的配置。必须按如下方式配置服务合同:

  • ServiceBehavior 属性的 ConcurrenyMode 属性必须分配以下 ConcurrencyMode.Multiple 值。
  • 对于所有操作, OperationBehavior 属性的 TransactionAutoComplete 属性必须为 true 。交易不能跨越多个操作。
  • 服务的 ServiceBehavior 属性的 ReleaseServiceInstanceOnTransactionComplete 属性必须设置为 false 。您必须通过关闭客户端的连接来显式释放服务实例。
  • 服务的 ServiceBehavior 属性的 TransactionAutoCompleteOnSessionClose 属性必须为 true 。会话结束时,必须终止所有线程中的所有事务。

    hadoop namenode -format
    

答案 1 :(得分:0)

我的猜测是因为你在提交事务之前关闭了客户端,至少从逻辑的角度看它应该是这样的:

Public Shared Function PdfVerarbeitungLoslegen(idAusGeplanteRechnungen As Integer, lettershopDrucken As Boolean) As Byte()

    Try
        Using transcop As New TransactionScope(TransactionScopeOption.Required, New TransactionOptions() With {.IsolationLevel = IsolationLevel.Serializable})
            Using client = New RechnungInternalWSClient("NetTcpBinding_IRechnungInternalWS")
                client.Open()
                Dim retval = client.PdfVerarbeitungLoslegen(idAusGeplanteRechnungen:=idAusGeplanteRechnungen, LettershopDrucken:=lettershopDrucken)
                transcop.Complete()                  
                Return retval
            End Using
        End Using
    Catch ex As Exception
        RechnungenUtils.ClientKontrolliertBeenden(client)
        Throw
    End Try

End Function