我有一个命令对象,根据请求队列的请求进行工作.这个特定的命令将在一个子应用程序域中执行它的工作.在子应用程序中执行其工作的一部分涉及阻止ConcurrentQueue操作(例如,Add或Take).我需要能够通过请求队列传播中止信号,跨越到子应用程序域,并唤醒其中的工作线程.
因此,我认为我需要通过AppDomain边界的CancellationToken.
我尝试创建一个继承自MarshalByRefObject的类:
protected class InterappDomainAbort : MarshalByRefObject,IAbortControl { public InterappDomainAbort(CancellationToken t) { Token = t; } [SecurityPermissionAttribute(SecurityAction.Demand,Flags = SecurityPermissionFlag.Infrastructure)] public override object InitializeLifetimeService() { return null; } public CancellationToken Token { get; private set; } };
并将其作为参数传递给worker函数:
// cts is an instance variable which can be triggered by another thread in parent appdomain cts = new CancellationTokenSource(); InterappDomainAbort abortFlag = new InterappDomainAbort(cts.Token); objectInRemoteAppDomain = childDomain.CreateInstanceAndUnwrap(...); // this call will block for a long while the work is being performed. objectInRemoteAppDomain.DoWork(abortFlag);
但是当objectInRemoteAppDomain尝试访问令牌getter属性时,我仍然会收到异常:
System.Runtime.Serialization.SerializationException: Type 'System.Threading.CancellationToken' in Assembly 'mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089' is not marked as serializable.
我的问题是:如何在appdomains中传播中止/取消信号,并唤醒可能在.NET并发数据结构中阻塞的线程(支持CancellationToken参数).
解决方法
已经有一段时间,因为我看着任何交叉AppDomain的东西,所以这个代码可能有问题,我还没有意识到,但它似乎是做这个工作.根本的问题是,似乎没有办法将CancellationToken [Source]从一个AppDomain转移到另一个AppDomain.所以我创建了两个来源,主要设置为适当时取消辅助.
事实上,在这种情况下有两个单独的令牌来源当然可能是一个问题,但是我不认为你不知道缺少可序列性阻止你在两个单独的AppDomains中使用相同的一个.
// I split this into a separate interface simply to make the boundary between // canceller and cancellee explicit,similar to CancellationTokenSource itself. public interface ITokenSource { CancellationToken Token { get; } } public class InterappDomainCancellable: MarshalByRefObject,ITokenSource,Idisposable { public InterappDomainCancellable() { cts = new CancellationTokenSource(); } public void Cancel() { cts.Cancel(); } // Explicitly implemented to make it less tempting to call Token // from the wrong side of the boundary. CancellationToken ITokenSource.Token { get { return cts.Token; } } public void dispose() { cts.dispose(); } private readonly CancellationTokenSource cts; } // ... // Crucial difference here is that the remotable cancellation source // also lives in the other domain. interappDomainCancellable = childDomain.CreateInstanceAndUnwrap(...); var primaryCts = new CancellationTokenSource(); // Cancel the secondary when the primary is cancelled. primaryCts.Token.Register(() => interappDomainCancellable.Cancel()); objectInRemoteAppDomain = childDomain.CreateInstanceAndUnwrap(...); // DoWork expects an instance of ITokenSource. // It can access Token because they're all in the same domain together. objectInRemoteAppDomain.DoWork(interappDomainCancellable);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。