我如何通过跨应用程序域边界的CancellationToken? [英] How do I pass CancellationToken across AppDomain boundary?

查看:200
本文介绍了我如何通过跨应用程序域边界的CancellationToken?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个命令对象,在做基于来自请求队列的请求的工作。这种特殊的命令将在一个孩子的AppDomain执行其工作。做的工作在孩子的AppDomain的一部分涉及堵在ConcurrentQueue操作(例如,添加或服用)。我需要能够通过请求队列传播中止信号,传达给子应用程序域,并在其中唤醒工作线程

I have a command object, doing work based on a request from a request queue. This particular command will execute its work in a child appdomain. Part of doing its work in the child appdomain involves blocking on a ConcurrentQueue operation (eg, Add or Take). I need to be able to propagate an abort signal through the request queue, across to the child appdomain, and to wake up the worker threads therein.

所以,我想我需要通过的CancellationToken跨AppDomain的边界。

Therefore, I think I need to pass a CancellationToken across the AppDomain boundary.

我试图创建一个类继承自MarshalByRefObject:

I tried creating a class which inherits from 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;
        }

    };

和传球这是对劳动者功能参数:

and passing this as an argument on the worker function:

// 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试图访问令牌吸气属性:

But I still get an exception when the objectInRemoteAppDomain tries to access the Token getter property:

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.

我的问题是:我怎样才能传播在整个应用程序域的中止/消除信号并唤醒可能被挡在.NET并发数据结构(其中支持的CancellationToken参数)线

My question is: How can I propagate the abort/cancellation signal across the appdomains and wake up threads that may be blocked in .NET concurrency data structures (where CancellationToken arguments are supported).

推荐答案

这已经有一段时间,因为我看了看任何交叉AppDomain的东西,所以可能会有问题,我还没有意识到这一点code,但它似乎做的工作。最根本的问题是,似乎没有办法从一个AppDomain中传输的CancellationToken [来源]到另一个。所以,我创建了两个来源,与主建立适当的时候取消次要的。

It's been a while since I looked at any cross-AppDomain stuff, so there might be problems with this code that I haven't realised, but it seems to do the job. The fundamental problem is that there seems no way to transfer a CancellationToken[Source] from one AppDomain to another. So I create two sources, with the primary set up to cancel the secondary when appropriate.

这也的的事实是的在此方案中两个独立的令牌来源可能,当然是一个问题,但我不认为你得到周围的事实,缺乏serialisability prevents您使用的同一个在两个单独的AppDomain反正。

The fact that there are two separate token sources in this scenario could of course be a problem, but I don't think you're getting around the fact that lack of serialisability prevents you from using the same one in two separate AppDomains anyway.

有关最小错误检查标准的警告,处置实现,等等。

Standard caveats about minimal error-checking, Dispose implementations, etc.

// 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);

这篇关于我如何通过跨应用程序域边界的CancellationToken?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆