Rebus,从异步处理程序创建 AppDomain / Instance 时出现异常

Posted

技术标签:

【中文标题】Rebus,从异步处理程序创建 AppDomain / Instance 时出现异常【英文标题】:Rebus, exception when creating AppDomain / Instance from async Handler 【发布时间】:2015-12-01 12:58:49 【问题描述】:

Rebus 的新(异步)版本存在问题,而旧版本不存在。

在处理 rebus 消息并尝试创建 AppDomain 和 Instance 以动态运行插件代码时,它总是给我一个异常。 为了使示例尽可能简单,我制作了一个 Test 方法:

public static void Test()

    AppDomain ad = AppDomain.CreateDomain("Test");
    Loader loader = (Loader)ad.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName);


class Loader : MarshalByRefObject


当我从“正常”代码调用该方法时,它可以工作,但是当我从(异步)Rebus 消息句柄方法调用它时,它会给出异常:

System.Runtime.Serialization.SerializationException 被捕获 HResult=-2146233076 消息=类型 程序集“Rebus”中的“Rebus.Transport.DefaultTransactionContext”, Version=1.0.0.0,Culture=neutral,PublicKeyToken=null' 未标记 作为可序列化的。来源=mscorlib 堆栈跟踪: 在 System.AppDomain.CreateInstanceAndUnwrap(字符串 assemblyName,字符串 typeName) 在 d:\Project\App.Bus.MessageParser\Process.cs:line 45 中的 App.Bus.MessageParse.Process.Test() 在 App.Bus.MessageParse.Process.d__0.MoveNext() 在 d:\Project\App.Bus.MessageParser\Process.cs:line 28 InnerException:

对这个问题有任何想法吗?

【问题讨论】:

【参考方案1】:

Rebus 将其事务上下文存储在AmbientTransactionContext.Current 中,该上下文由线程的逻辑调用上下文支持,当您await 某事时,它会自动流向延续。

显然,它也流向创建的应用程序域;)

可以将 DefaultTransactionContext 标记为可序列化,但我担心你会得到一个异常,告诉你事务上下文字典中的项目不可序列化。

我无法使事务上下文真正可序列化并保证它可以工作,所以 - 如果您需要在消息处理程序中创建应用程序域 - 我建议您暂时删除环境事务上下文 - 只需记住将它又回来了:)

类似下面的东西应该可以解决问题:

public async Task Handle(SomeMessage message)

    var transactionContext = AmbientTransactionContext.Current;
    AmbientTransactionContext.Current = null;
    try
    
        JuggleWithAppDomainsInHere();
    
    finally
    
        AmbientTransactionContext.Current = transactionContext;
    

如果在您的应用程序中使用 appdomains 进行操作是一种常见模式,我建议您将“removing-and-restoreing-of-the-ambient-Rebus-transaction”包装在 IDisposable 中,这样您就可以

using(new DismantleAmbientRebusStuff())

    JuggleWithAppDomainsInHere();

【讨论】:

以上是关于Rebus,从异步处理程序创建 AppDomain / Instance 时出现异常的主要内容,如果未能解决你的问题,请参考以下文章

远程处理:从服务器 AppDomain 查找客户端 AppDomain / Assembly

从 AppDomain 创建实例时程序集未解析

AppDomain 等待异步任务防止 SerializationException

创建从 AppDomain 引用的对象的本地实例

Azure Queues dequeue 计数随着 Rebus 核心增长

在沙盒 Appdomain 中加载程序集 - SecurityException