C# で記述された IIS でホストされている Web アプリがあります。サービス呼び出しで、新しい AppDomain を作成し、それを読み込んだ後に dll を実行します。実行時間が 10 分を超えると、次の Remoting 例外が発生します。
System.Runtime.Remoting.RemotingException: オブジェクト '/a3178091_1732_4272_b0bd_dae31e328450/lwntwiaw53jg1rd9gbvsigbe_25.rem' が切断されたか、サーバーに存在しません。
サーバー スタック トレース:
System.Runtime.Remoting.Channels.ChannelServices.CheckDisconnectedOrCreateWellKnownObject (IMessage メッセージ) で
System.Runtime.Remoting.Channels.ChannelServices.SyncDispatchMessage (IMessage メッセージ) で
[0] で例外が再スローされました:
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage (IMessage reqMsg、IMessage retMsg) で
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (MessageData& msgData、Int32 型) で
System.IO.Stream.set_Position (Int64 値) で
アプリドメインを作成する方法は次のとおりです
private AppDomain CreateDomainForTaskExecution(string baseDirectory)
{
AppDomainSetup domainSetup = new AppDomainSetup();
domainSetup.ApplicationBase = baseDirectory;
domainSetup.PrivateBinPath = baseDirectory;
return AppDomain.CreateDomain("Domain for task execution", null, domainSetup);
}
次に、サービス呼び出しでリモート オブジェクトを呼び出します。
newDomain = CreateDomainForTaskExecution(domainBaseDir);
IExecutableTaskFactory taskLocator = (IExecutableTaskFactory)newDomain.CreateInstanceFromAndUnwrap(taskAssemblyFile.FullName, this.ExecutableTaskFactoryFullName);
IExecutableTask executableTask = taskLocator.Create();
IList<uint> ouputArguments = executableTask.OutputArgumentNames;
IDictionary<uint, Stream> taskOutput = new Dictionary<uint, Stream>();
foreach (uint argument in ouputArguments)
{
MarshalByRefObject stream = new MemoryStream();
taskOutput[argument] = stream as Stream;
ILease lease = (ILease)stream.InitializeLifetimeService();
if (lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.Zero;
//lease.SponsorshipTimeout = TimeSpan.FromMinutes(30);
//lease.RenewOnCallTime = TimeSpan.FromMinutes(30);
}
lease.Register(this);
}
// Register as a sponsor.
foreach (Stream stream in inputArguments.Values)
{
ILease lease = (ILease)stream.InitializeLifetimeService();
if (lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.Zero;
//lease.SponsorshipTimeout = TimeSpan.FromMinutes(30);
//lease.RenewOnCallTime = TimeSpan.FromMinutes(30);
}
lease.Register(this);
}
executableTask.Execute(inputArguments, taskOutput);
return taskOutput;
taskLocator は MarshalByRefObject であり、次のように InitializeLifetimeService() 関数をオーバーライドします。
public override object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
if (lease.CurrentState == LeaseState.Initial)
{
lease.InitialLeaseTime = TimeSpan.Zero;
//lease.SponsorshipTimeout = TimeSpan.FromMinutes(30);
//lease.RenewOnCallTime = TimeSpan.FromMinutes(30);
}
return lease;
}
executableTask も MarshalByRefObject であり、同様に上記のように無制限の Lease を取得しようとします。
また、サービス オブジェクトを ISponsor にしようとしましたが、Renew でそうします
public TimeSpan Renewal(ILease lease)
{
return TimeSpan.FromMinutes(5);
}
しかし、更新は決して呼び出されません。Google とスタック オーバーフローですべてのリンクを調べましたが、解決策が見つかりませんでした。考えられる問題は何ですか?