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 等待异步任务防止 SerializationException