Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 为什么跨AppDomain调用后Transaction.Current变为空?_.net_Appdomain_Remoting_Transactionscope_System.transactions - Fatal编程技术网

.net 为什么跨AppDomain调用后Transaction.Current变为空?

.net 为什么跨AppDomain调用后Transaction.Current变为空?,.net,appdomain,remoting,transactionscope,system.transactions,.net,Appdomain,Remoting,Transactionscope,System.transactions,考虑下面的小程序,它简单地创建一个TransactionScope,打印Transaction.Current,调用另一个AppDomain中的一个方法(执行需要一段时间),然后在返回时打印Transaction.Current using System; using System.Linq; using System.Runtime.Remoting.Lifetime; using System.Threading; using System.Transactions; namespace

考虑下面的小程序,它简单地创建一个
TransactionScope
,打印
Transaction.Current
,调用另一个AppDomain中的一个方法(执行需要一段时间),然后在返回时打印
Transaction.Current

using System;

using System.Linq;
using System.Runtime.Remoting.Lifetime;
using System.Threading;
using System.Transactions;

namespace TransactionScopeFlowTest
{
   class Program
   {
      static void Main(string[] args)
      {
         // These times are just to generate the error faster. Normally the initial lease is 5 minutes, meaning the method call
         // would have to take 5 minutes to occur, so we speed it up here for demonstration purposes.
         LifetimeServices.LeaseManagerPollTime = TimeSpan.FromSeconds(1);
         LifetimeServices.LeaseTime = TimeSpan.FromSeconds(1);
         LifetimeServices.RenewOnCallTime = TimeSpan.FromSeconds(1);

         AppDomain domain = AppDomain.CreateDomain("Temp", null, AppDomain.CurrentDomain.SetupInformation);

         using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
         {
            Console.WriteLine($"Transaction Before Call = {Transaction.Current?.TransactionInformation?.LocalIdentifier?.ToString() ?? "<null>"}");
            domain.DoCallBack(AppDomainCallback);
            Console.WriteLine($"Transaction After Call = {Transaction.Current?.TransactionInformation?.LocalIdentifier?.ToString() ?? "<null>"}");
            scope.Complete();
         }

         AppDomain.Unload(domain);
      }

      public static void AppDomainCallback()
      {
         Thread.Sleep(3000);
      }
   }
}
使用系统;
使用System.Linq;
使用System.Runtime.Remoting.Lifetime;
使用系统线程;
使用系统事务;
命名空间TransactionScopeFlowTest
{
班级计划
{
静态void Main(字符串[]参数)
{
//这些时间只是为了更快地生成错误。通常初始租约是5分钟,这意味着方法调用
//将需要5分钟才能发生,因此为了演示,我们在这里加快了速度。
LifetimeServices.LeaseManagerPollTime=TimeSpan.FromSeconds(1);
LifetimeServices.LeaseTime=TimeSpan.FromSeconds(1);
LifetimeServices.RenewOnCallTime=TimeSpan.FromSeconds(1);
AppDomain域=AppDomain.CreateDomain(“Temp”,null,AppDomain.CurrentDomain.SetupInformation);
使用(TransactionScope作用域=新TransactionScope(TransactionScope异步流选项.Enabled))
{
Console.WriteLine($“调用前的事务={Transaction.Current?.TransactionInformation?.LocalIdentifier?.ToString()??“}”);
domain.DoCallBack(AppDomainCallback);
Console.WriteLine($“调用后的事务={Transaction.Current?.TransactionInformation?.LocalIdentifier?.ToString()??“}”);
scope.Complete();
}
卸载(域);
}
公共静态void AppDomainCallback()
{
睡眠(3000);
}
}
}
出乎意料的是,程序生成了以下输出:

Transaction Before Call = 1f980219-2583-4796-8d6d-256a6f100698:1
Transaction After Call = <null>
调用前事务=1f980219-2583-4796-8d6d-256a6f100698:1 调用后的事务= 如果我将
TransactionScope
的ctor中的
TransactionScopeAsyncFlowOption
更改为
TransactionScopeAsyncFlowOption.Suppress
,则该事务在调用后保留

我怀疑跨逻辑上下文的事务作用域流是由CallContext处理的,CallContext在远程处理调用中传播,使用的键继承了
MarshalByRefObject
,并且由于它们没有向任何
ISponsor
注册,代理将在初始租用时间后断开连接。然后,一旦我们从调用返回,逻辑调用上下文就会与原始上下文合并,这意味着事务不再存在


我正在寻找一种方法来避免这个问题,而且如果这被认为是.NET中的一个bug呢?

你已经说了。参考资料显示,当您需要AsyncFlow时,事务状态使用MarshallByRefObject ContextKey类:事实是,事务不会按设计在AppDomains之间流动:“对于异步流场景,我们不应该允许事务在应用程序域之间流动”。没有“合并回”。存储为弱引用的密钥刚刚消失,因此事务似乎从未存在过。我不确定这是一只虫子。我看不到一个简单的解决方案,但向Microsoft报告(或者停止对很久以前设计的糟糕TransactionScope进行花哨的处理,甚至在.NET存在之前:-)我知道该事务不会在调用中流动,并且我不会在其他AppDomain中使用该事务。奇怪的是,在调用后,事务在原始AppDomain中消失。因为ContextKey实例在域之间应该是相同的,一旦它在临时域中由于租约时间而被终止,其他域也会终止。因为它最初存储在一个弱引用字典中:对于初始域,它好像从未存在过。这个问题在