WCF + TransactionScopeRequired + async + throw fault => ProtocolException“正在执行哪个方法的事务被异步中止”

问题描述 投票:0回答:1

在使用异步主机实现(在我的情况下使用Tasks)的服务上调用标记为“TransactionScopeRequired = true”的WCF操作并异步抛出异常(即从延续中),似乎总是导致以下异常(而不是我扔的例外)在客户端收到:

System.AggregateException: One or more errors occurred. ---> System.ServiceModel.ProtocolException: The transaction under which this method call was executing was asynchronously aborted.
   at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass6_0.<CreateTask>b__0(IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at WcfTransactionScopeRequiredAsync.Program.Main(String[] args) in D:\\WcfTransactionScopeRequiredAsync\\WcfTransactionScopeRequiredAsync.Client\\Program.cs:line 19
---> (Inner Exception #0) System.ServiceModel.ProtocolException: The transaction under which this method call was executing was asynchronously aborted.
   at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass6_0.<CreateTask>b__0(IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)<---

服务合约:

[ServiceContract]
public interface IService
{
    [FaultContract(typeof(SomeFault))]
    [TransactionFlow(TransactionFlowOption.Allowed)]
    [OperationContract]
    Task DoItAsync();
}

服务主机实施:

[OperationBehavior(TransactionScopeRequired = true)]
public async Task DoItAsync()
{
    using (TransactionScope tx = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled))
    {
        await Task.Delay(1000).ConfigureAwait(continueOnCapturedContext: false);
        throw new FaultException<SomeFault>(new SomeFault());
        tx.Complete();
    }
}

客户端是同步的:

service.DoItAsync().Wait();

在这种情况下,客户端不会流动事务(因此这绝对不是分布式事务(通过检查Transaction.Current.TransactionInformation.DistributedIdentifier来验证)。

此代码使用.NET framework 4.7.2进行了测试。

到目前为止,我的研究表明,这个ProtocolException是由服务主机上的WCF管道引发的(从Exception中的堆栈跟踪中也很明显),并且应该用于处理在主机控制之外中止的分布式事务(即, DTC发布中止)。虽然这似乎有道理,但这显然不是这里的情况。

有没有办法在主机上仍然使用异步实现时避免此ProtocolException?

c# wcf async-await transactionscope protocolexception
1个回答
0
投票

有没有办法在主机上仍然使用异步实现时避免此ProtocolException?

看起来您不应该在服务主机实现中创建自己的TransactionScope实例,而是仅依赖于WCF管道创建的TransactionScope。

我相应地调整了上面的服务主机实现代码,并且ProtocolException消失了(我现在在客户端上获得FaultException)。

关于this post的评论让我走上正轨。

© www.soinside.com 2019 - 2024. All rights reserved.