Почему Transaction.Current становится нулевым после вызова Cross-AppDomain?
Рассмотрим следующую небольшую программу, которая просто создает 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);
}
}
}
Совершенно неожиданно программа генерирует следующий вывод:
Transaction Before Call = 1f980219-2583-4796-8d6d-256a6f100698:1
Transaction After Call = <null>
Если я изменю TransactionScopeAsyncFlowOption
в центре TransactionScope
в TransactionScopeAsyncFlowOption.Suppress
, то Транзакция остается после звонка.
Я подозреваю, что поток области транзакции через логический контекст обрабатывается CallContext, который распространяется по вызову удаленного взаимодействия, а используемые ключи наследуются MarshalByRefObject
и так как они не зарегистрированы ни с какими ISponsor
, прокси отключится после первоначального времени аренды. А затем, когда мы возвращаемся из вызова, контекст логического вызова объединяется с оригиналом, что означает, что транзакция больше не существует.
Я ищу способ обойти эту проблему, а также, если это считается ошибкой в .NET?